first commit
This commit is contained in:
+460
@@ -0,0 +1,460 @@
|
||||
package orm_test
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
orm "trankilou.fr/lasebuche"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID string `db:"id" json:"id"`
|
||||
Firstname string `db:"firstname" json:"firstname,omitempty"`
|
||||
Lastname string `db:"lastname" json:"lastname,omitempty"`
|
||||
Password string `db:"password" json:"-"`
|
||||
Email string `db:"email" json:"email,omitempty"`
|
||||
PictureID *string `db:"picture" json:"picture,omitempty"`
|
||||
Enabled bool `db:"enabled" json:"enabled"`
|
||||
Theme string `db:"theme" json:"theme"`
|
||||
Lang string `db:"lang" json:"lang"`
|
||||
Content []byte `db:"content" json:"content"`
|
||||
DateCreated time.Time `db:"_date_created" json:"_date_created"`
|
||||
DateUpdated *time.Time `db:"_date_updated" json:"_date_updated"`
|
||||
VersionId string `db:"_version" json:"_version"`
|
||||
}
|
||||
|
||||
func TestHelloName(t *testing.T) {
|
||||
db, err := sql.Open("sqlite", "testdb")
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
dialect := orm.NewSqliteDialect()
|
||||
tableUser, err := orm.NewTable[User](db, dialect, User{}, "user")
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
tableUser.Debug()
|
||||
|
||||
err = tableUser.Sync()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Firstname: "fabien",
|
||||
Lastname: "masson",
|
||||
Email: "masson.fabien@gmail.com",
|
||||
}
|
||||
user, err = tableUser.Insert(user)
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
id := user.ID
|
||||
user2, err := tableUser.Get(id)
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
if user2.Firstname != "fabien" {
|
||||
t.Errorf("GetByID : expected %s, got %s", "fabien", user2.Firstname)
|
||||
}
|
||||
|
||||
// Test SelectOne
|
||||
user3, err := tableUser.SelectOne("firstname = $1", "fabien")
|
||||
if err != nil {
|
||||
t.Errorf("SelectOne failed: %v", err)
|
||||
}
|
||||
if user3 == nil {
|
||||
t.Error("SelectOne returned nil")
|
||||
}
|
||||
if user3.Firstname != "fabien" {
|
||||
t.Errorf("SelectOne: expected firstname %s, got %s", "fabien", user3.Firstname)
|
||||
}
|
||||
|
||||
// Test SelectWhere
|
||||
users, err := tableUser.SelectWhere("firstname = $1", "fabien")
|
||||
if err != nil {
|
||||
t.Errorf("SelectWhere failed: %v", err)
|
||||
}
|
||||
if len(users) == 0 {
|
||||
t.Error("SelectWhere returned no results")
|
||||
}
|
||||
|
||||
// Test Update
|
||||
user.Firstname = "Fabien"
|
||||
updatedUser, err := tableUser.Update(user)
|
||||
if err != nil {
|
||||
t.Errorf("Update failed: %v", err)
|
||||
}
|
||||
if updatedUser.Firstname != "Fabien" {
|
||||
t.Errorf("Update: expected firstname %s, got %s", "Fabien", updatedUser.Firstname)
|
||||
}
|
||||
|
||||
// Verify update with Get
|
||||
user4, err := tableUser.Get(id)
|
||||
if err != nil {
|
||||
t.Errorf("Get after update failed: %v", err)
|
||||
}
|
||||
if user4.Firstname != "Fabien" {
|
||||
t.Errorf("After update, Get: expected firstname %s, got %s", "Fabien", user4.Firstname)
|
||||
}
|
||||
|
||||
// Test Delete
|
||||
err = tableUser.Delete(id)
|
||||
if err != nil {
|
||||
t.Errorf("Delete failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify delete
|
||||
_, err = tableUser.Get(id)
|
||||
if err != sql.ErrNoRows {
|
||||
t.Errorf("After delete, expected ErrNoRows, got: %v", err)
|
||||
}
|
||||
|
||||
// Test DeleteWhere - insert another user first
|
||||
user5 := &User{
|
||||
Firstname: "Test",
|
||||
Lastname: "User",
|
||||
Email: "test@example.com",
|
||||
}
|
||||
user5, err = tableUser.Insert(user5)
|
||||
if err != nil {
|
||||
t.Errorf("Insert for DeleteWhere test failed: %v", err)
|
||||
}
|
||||
|
||||
// Delete the test user
|
||||
err = tableUser.DeleteWhere("firstname = $1", "Test")
|
||||
if err != nil {
|
||||
t.Errorf("DeleteWhere failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify delete
|
||||
_, err = tableUser.Get(user5.ID)
|
||||
if err != sql.ErrNoRows {
|
||||
t.Errorf("After DeleteWhere, expected ErrNoRows, got: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCRUDOperations(t *testing.T) {
|
||||
db, err := sql.Open("sqlite", "testdb")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
dialect := orm.NewSqliteDialect()
|
||||
tableUser, err := orm.NewTable[User](db, dialect, User{}, "user")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Clean up before test
|
||||
_, err = db.Exec("DELETE FROM user")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Test Insert
|
||||
user1 := &User{
|
||||
Firstname: "John",
|
||||
Lastname: "Doe",
|
||||
Email: "john.doe@example.com",
|
||||
Enabled: true,
|
||||
Theme: "dark",
|
||||
Lang: "en",
|
||||
}
|
||||
|
||||
insertedUser, err := tableUser.Insert(user1)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert failed: %v", err)
|
||||
}
|
||||
if insertedUser.ID == "" {
|
||||
t.Error("Inserted user should have an ID")
|
||||
}
|
||||
if insertedUser.VersionId == "" {
|
||||
t.Error("Inserted user should have a VersionId")
|
||||
}
|
||||
if insertedUser.DateCreated.IsZero() {
|
||||
t.Error("Inserted user should have DateCreated set")
|
||||
}
|
||||
|
||||
t.Logf("Inserted user with ID: %s, VersionId: %s", insertedUser.ID, insertedUser.VersionId)
|
||||
|
||||
// Test Get
|
||||
fetchedUser, err := tableUser.Get(insertedUser.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Get failed: %v", err)
|
||||
}
|
||||
if fetchedUser.ID != insertedUser.ID {
|
||||
t.Errorf("Get: expected ID %s, got %s", insertedUser.ID, fetchedUser.ID)
|
||||
}
|
||||
if fetchedUser.Firstname != "John" {
|
||||
t.Errorf("Get: expected Firstname John, got %s", fetchedUser.Firstname)
|
||||
}
|
||||
|
||||
// Test Update
|
||||
fetchedUser.Firstname = "Jane"
|
||||
updatedUser, err := tableUser.Update(fetchedUser)
|
||||
if err != nil {
|
||||
t.Fatalf("Update failed: %v", err)
|
||||
}
|
||||
if updatedUser.Firstname != "Jane" {
|
||||
t.Errorf("Update: expected Firstname Jane, got %s", updatedUser.Firstname)
|
||||
}
|
||||
if updatedUser.DateUpdated == nil {
|
||||
t.Error("Update should have set DateUpdated")
|
||||
}
|
||||
|
||||
// Verify update
|
||||
verifiedUser, err := tableUser.Get(insertedUser.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Get after update failed: %v", err)
|
||||
}
|
||||
if verifiedUser.Firstname != "Jane" {
|
||||
t.Errorf("After update, Get: expected Firstname Jane, got %s", verifiedUser.Firstname)
|
||||
}
|
||||
|
||||
// Test SelectOne
|
||||
selectedUser, err := tableUser.SelectOne("email = $1", "john.doe@example.com")
|
||||
if err != nil {
|
||||
t.Fatalf("SelectOne failed: %v", err)
|
||||
}
|
||||
if selectedUser == nil {
|
||||
t.Error("SelectOne returned nil")
|
||||
}
|
||||
if selectedUser.Email != "john.doe@example.com" {
|
||||
t.Errorf("SelectOne: expected email john.doe@example.com, got %s", selectedUser.Email)
|
||||
}
|
||||
|
||||
// Insert another user for SelectWhere test
|
||||
user2 := &User{
|
||||
Firstname: "Alice",
|
||||
Lastname: "Smith",
|
||||
Email: "alice.smith@example.com",
|
||||
}
|
||||
_, err = tableUser.Insert(user2)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert user2 failed: %v", err)
|
||||
}
|
||||
|
||||
// Test SelectWhere
|
||||
users, err := tableUser.SelectWhere("")
|
||||
if err != nil {
|
||||
t.Fatalf("SelectWhere failed: %v", err)
|
||||
}
|
||||
if len(users) < 2 {
|
||||
t.Errorf("SelectWhere: expected at least 2 users, got %d", len(users))
|
||||
}
|
||||
|
||||
// Test SelectWhere with condition
|
||||
filteredUsers, err := tableUser.SelectWhere("firstname = $1", "Jane")
|
||||
if err != nil {
|
||||
t.Fatalf("SelectWhere with condition failed: %v", err)
|
||||
}
|
||||
if len(filteredUsers) != 1 {
|
||||
t.Errorf("SelectWhere with condition: expected 1 user, got %d", len(filteredUsers))
|
||||
}
|
||||
|
||||
// Test Delete
|
||||
err = tableUser.Delete(insertedUser.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Delete failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify deletion
|
||||
_, err = tableUser.Get(insertedUser.ID)
|
||||
if err != sql.ErrNoRows {
|
||||
t.Errorf("After Delete, expected ErrNoRows, got: %v", err)
|
||||
}
|
||||
|
||||
// Test DeleteWhere
|
||||
err = tableUser.DeleteWhere("firstname = $1", "Alice")
|
||||
if err != nil {
|
||||
t.Fatalf("DeleteWhere failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify deletion
|
||||
_, err = tableUser.Get(user2.ID)
|
||||
if err != sql.ErrNoRows {
|
||||
t.Errorf("After DeleteWhere, expected ErrNoRows, got: %v", err)
|
||||
}
|
||||
|
||||
// Clean up
|
||||
_, err = db.Exec("DELETE FROM user")
|
||||
if err != nil {
|
||||
t.Logf("Cleanup failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEdgeCases(t *testing.T) {
|
||||
db, err := sql.Open("sqlite", "testdb")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
dialect := orm.NewSqliteDialect()
|
||||
tableUser, err := orm.NewTable[User](db, dialect, User{}, "user")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Clean up before test
|
||||
_, err = db.Exec("DELETE FROM user")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Test SelectOne with no results
|
||||
user, err := tableUser.SelectOne("firstname = $1", "NonExistent")
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
t.Errorf("SelectOne with no results: expected error or nil, got: %v", err)
|
||||
}
|
||||
if user != nil {
|
||||
t.Error("SelectOne with no results should return nil user")
|
||||
}
|
||||
|
||||
// Test SelectWhere with no results
|
||||
users, err := tableUser.SelectWhere("firstname = $1", "NonExistent")
|
||||
if err != nil {
|
||||
t.Errorf("SelectWhere with no results: unexpected error: %v", err)
|
||||
}
|
||||
if len(users) != 0 {
|
||||
t.Errorf("SelectWhere with no results: expected 0 users, got %d", len(users))
|
||||
}
|
||||
|
||||
// Test Get with non-existent ID
|
||||
_, err = tableUser.Get("non-existent-id")
|
||||
if err != sql.ErrNoRows {
|
||||
t.Errorf("Get with non-existent ID: expected ErrNoRows, got: %v", err)
|
||||
}
|
||||
|
||||
// Test Delete with non-existent ID (should not error, just affect 0 rows)
|
||||
err = tableUser.Delete("non-existent-id")
|
||||
if err != nil {
|
||||
t.Errorf("Delete with non-existent ID: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Test DeleteWhere with no matching rows
|
||||
err = tableUser.DeleteWhere("firstname = $1", "NonExistent")
|
||||
if err != nil {
|
||||
t.Errorf("DeleteWhere with no matching rows: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Test Update with non-existent ID (will fail due to WHERE clause)
|
||||
nonExistentUser := &User{
|
||||
ID: "non-existent-id",
|
||||
Firstname: "Test",
|
||||
VersionId: "test-version",
|
||||
}
|
||||
_, err = tableUser.Update(nonExistentUser)
|
||||
// This should fail because the row doesn't exist
|
||||
if err == nil {
|
||||
t.Error("Update with non-existent ID should have failed")
|
||||
}
|
||||
|
||||
// Clean up
|
||||
_, err = db.Exec("DELETE FROM user")
|
||||
if err != nil {
|
||||
t.Logf("Cleanup failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionLocking(t *testing.T) {
|
||||
db, err := sql.Open("sqlite", "testdb")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
dialect := orm.NewSqliteDialect()
|
||||
tableUser, err := orm.NewTable[User](db, dialect, User{}, "user")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Clean up before test
|
||||
_, err = db.Exec("DELETE FROM user")
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Insert a user
|
||||
user := &User{
|
||||
Firstname: "Version",
|
||||
Lastname: "Test",
|
||||
Email: "version@test.com",
|
||||
}
|
||||
|
||||
insertedUser, err := tableUser.Insert(user)
|
||||
if err != nil {
|
||||
t.Fatalf("Insert failed: %v", err)
|
||||
}
|
||||
|
||||
originalVersionId := insertedUser.VersionId
|
||||
t.Logf("Original VersionId: %s", originalVersionId)
|
||||
|
||||
// Fetch the user to get fresh data
|
||||
fetchedUser, err := tableUser.Get(insertedUser.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Get failed: %v", err)
|
||||
}
|
||||
|
||||
// First update should succeed with correct version
|
||||
fetchedUser.Firstname = "Version2"
|
||||
updatedUser, err := tableUser.Update(fetchedUser)
|
||||
if err != nil {
|
||||
t.Fatalf("First update failed: %v", err)
|
||||
}
|
||||
|
||||
// VersionId should have changed
|
||||
if updatedUser.VersionId == originalVersionId {
|
||||
t.Error("VersionId should have changed after update")
|
||||
}
|
||||
|
||||
newVersionId := updatedUser.VersionId
|
||||
t.Logf("New VersionId after first update: %s", newVersionId)
|
||||
|
||||
// Second update with correct version should succeed
|
||||
updatedUser.Firstname = "Version3"
|
||||
updatedUser2, err := tableUser.Update(updatedUser)
|
||||
if err != nil {
|
||||
t.Fatalf("Second update failed: %v", err)
|
||||
}
|
||||
|
||||
// VersionId should have changed again
|
||||
if updatedUser2.VersionId == newVersionId {
|
||||
t.Error("VersionId should have changed after second update")
|
||||
}
|
||||
|
||||
// Now try to update with old version - should fail
|
||||
// Create a new user with the old version
|
||||
oldVersionUser := &User{
|
||||
ID: insertedUser.ID,
|
||||
Firstname: "ShouldFail",
|
||||
Lastname: "Test",
|
||||
Email: "version@test.com",
|
||||
VersionId: originalVersionId, // Old version
|
||||
}
|
||||
|
||||
_, err = tableUser.Update(oldVersionUser)
|
||||
if err == nil {
|
||||
t.Error("Update with old VersionId should have failed")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "version mismatch") {
|
||||
t.Errorf("Expected version mismatch error, got: %v", err)
|
||||
}
|
||||
|
||||
// Clean up
|
||||
_, err = db.Exec("DELETE FROM user")
|
||||
if err != nil {
|
||||
t.Logf("Cleanup failed: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user