461 lines
12 KiB
Go
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)
|
|
}
|
|
}
|