Files
lasebuche/orm_test.go
T

461 lines
12 KiB
Go

package lasebuche_test
import (
"database/sql"
"strings"
"testing"
"time"
"gitea.trankilou.fr/fabien/lasebuche"
_ "modernc.org/sqlite"
)
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 := lasebuche.NewSqliteDialect()
tableUser, err := lasebuche.NewTable[User](db, dialect, "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 := lasebuche.NewSqliteDialect()
tableUser, err := lasebuche.NewTable[User](db, dialect, "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 := lasebuche.NewSqliteDialect()
tableUser, err := lasebuche.NewTable[User](db, dialect, "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 := lasebuche.NewSqliteDialect()
tableUser, err := lasebuche.NewTable[User](db, dialect, "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)
}
}