diff --git a/auth/auth_test.go b/auth/auth_test.go new file mode 100644 index 0000000..d1977ba --- /dev/null +++ b/auth/auth_test.go @@ -0,0 +1,48 @@ +package auth + +import ( + "os" + "testing" + + "golang.org/x/crypto/bcrypt" +) + +func TestPasswordAuth(t *testing.T) { + hash, _ := bcrypt.GenerateFromPassword([]byte("secret"), bcrypt.DefaultCost) + auth := NewPasswordAuth(string(hash)) + + if err := auth.Authenticate("", "secret"); err != nil { + t.Errorf("expected success, got %v", err) + } + + if err := auth.Authenticate("", "wrong"); err == nil { + t.Error("expected failure for wrong password") + } +} + +func TestHtpasswdAuth(t *testing.T) { + hash, _ := bcrypt.GenerateFromPassword([]byte("mypass"), bcrypt.DefaultCost) + content := "alice:" + string(hash) + "\n" + + f, err := os.CreateTemp("", "htpasswd") + if err != nil { + t.Fatal(err) + } + defer os.Remove(f.Name()) + f.WriteString(content) + f.Close() + + auth := NewHtpasswdAuth(f.Name()) + + if err := auth.Authenticate("alice", "mypass"); err != nil { + t.Errorf("expected success, got %v", err) + } + + if err := auth.Authenticate("alice", "wrong"); err == nil { + t.Error("expected failure for wrong password") + } + + if err := auth.Authenticate("bob", "mypass"); err == nil { + t.Error("expected failure for unknown user") + } +} diff --git a/linkgen/linkgen_test.go b/linkgen/linkgen_test.go new file mode 100644 index 0000000..dc6cf78 --- /dev/null +++ b/linkgen/linkgen_test.go @@ -0,0 +1,75 @@ +package linkgen + +import ( + "context" + "testing" + "time" + + "github.com/parkan/go-hauk/config" +) + +type mockStore struct{} + +func (m *mockStore) Get(_ context.Context, _ string, _ any) error { return nil } +func (m *mockStore) Set(_ context.Context, _ string, _ any, _ time.Time) error { return nil } +func (m *mockStore) SetTTL(_ context.Context, _ string, _ any, _ time.Duration) error { return nil } +func (m *mockStore) Delete(_ context.Context, _ string) error { return nil } +func (m *mockStore) Exists(_ context.Context, _ string) (bool, error) { return false, nil } + +func TestGenerate4Plus4Upper(t *testing.T) { + g := New(&mockStore{}, config.Link4Plus4Upper) + id, err := g.Generate(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(id) != 9 { + t.Errorf("expected 9 chars, got %d: %s", len(id), id) + } + if id[4] != '-' { + t.Errorf("expected dash at position 4: %s", id) + } +} + +func TestGenerate4Plus4Lower(t *testing.T) { + g := New(&mockStore{}, config.Link4Plus4Lower) + id, err := g.Generate(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(id) != 9 { + t.Errorf("expected 9 chars, got %d: %s", len(id), id) + } +} + +func TestGenerateUUID(t *testing.T) { + g := New(&mockStore{}, config.LinkUUIDv4) + id, err := g.Generate(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(id) != 36 { + t.Errorf("expected 36 chars, got %d: %s", len(id), id) + } +} + +func TestGenerate16Hex(t *testing.T) { + g := New(&mockStore{}, config.Link16Hex) + id, err := g.Generate(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(id) != 16 { + t.Errorf("expected 16 chars, got %d: %s", len(id), id) + } +} + +func TestGenerate32Hex(t *testing.T) { + g := New(&mockStore{}, config.Link32Hex) + id, err := g.Generate(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(id) != 32 { + t.Errorf("expected 32 chars, got %d: %s", len(id), id) + } +} diff --git a/model/session_test.go b/model/session_test.go new file mode 100644 index 0000000..be4e204 --- /dev/null +++ b/model/session_test.go @@ -0,0 +1,62 @@ +package model + +import ( + "testing" + "time" +) + +func TestSessionAddPoint(t *testing.T) { + sess := &Session{ + maxPts: 3, + data: SessionData{ + Points: [][]any{}, + }, + } + + for i := 0; i < 5; i++ { + sess.AddPoint([]any{float64(i), float64(i), float64(i), 0, nil, nil}) + } + + if len(sess.data.Points) != 3 { + t.Errorf("expected 3 points, got %d", len(sess.data.Points)) + } + + if sess.data.Points[0][0].(float64) != 2 { + t.Errorf("expected oldest point to be 2, got %v", sess.data.Points[0][0]) + } +} + +func TestSessionGetPoints(t *testing.T) { + sess := &Session{ + maxPts: 10, + data: SessionData{ + Points: [][]any{ + {1.0, 1.0, 100.0, 0, nil, nil}, + {2.0, 2.0, 200.0, 0, nil, nil}, + {3.0, 3.0, 300.0, 0, nil, nil}, + }, + }, + } + + pts := sess.GetPoints(150) + if len(pts) != 2 { + t.Errorf("expected 2 points after since=150, got %d", len(pts)) + } +} + +func TestSessionExpired(t *testing.T) { + sess := &Session{ + data: SessionData{ + Expire: time.Now().Add(-time.Hour).Unix(), + }, + } + + if !sess.HasExpired() { + t.Error("expected session to be expired") + } + + sess.data.Expire = time.Now().Add(time.Hour).Unix() + if sess.HasExpired() { + t.Error("expected session to not be expired") + } +}