1+ package crud
2+
3+ import (
4+ "context"
5+ "testing"
6+ "time"
7+ )
8+
9+ type TestEntity struct {
10+ ID int64 `json:"id"`
11+ Name string `json:"name"`
12+ CreatedAt time.Time `json:"created_at"`
13+ UpdatedAt time.Time `json:"updated_at"`
14+ }
15+
16+ func (e TestEntity ) GetID () int64 {
17+ return e .ID
18+ }
19+
20+ func (e TestEntity ) GetName () string {
21+ return e .Name
22+ }
23+
24+ func (e TestEntity ) GetCreatedAt () time.Time {
25+ return e .CreatedAt
26+ }
27+
28+ func (e TestEntity ) GetUpdatedAt () time.Time {
29+ return e .UpdatedAt
30+ }
31+
32+ func TestCRUDInterface (t * testing.T ) {
33+ ctx := context .Background ()
34+
35+ t .Run ("Create" , func (t * testing.T ) {
36+ manager := & testCRUDManager {}
37+
38+ entity , err := manager .Create (ctx , "test-entity" )
39+ if err != nil {
40+ t .Fatalf ("Create failed: %v" , err )
41+ }
42+
43+ if entity .GetName () != "test-entity" {
44+ t .Errorf ("expected name 'test-entity', got %s" , entity .GetName ())
45+ }
46+
47+ if entity .GetID () == 0 {
48+ t .Error ("expected ID to be set" )
49+ }
50+
51+ if entity .GetCreatedAt ().IsZero () {
52+ t .Error ("expected CreatedAt to be set" )
53+ }
54+ })
55+
56+ t .Run ("Read" , func (t * testing.T ) {
57+ manager := & testCRUDManager {}
58+
59+ // Create entity first
60+ created , err := manager .Create (ctx , "test-read" )
61+ if err != nil {
62+ t .Fatalf ("Create failed: %v" , err )
63+ }
64+
65+ // Read it back
66+ entity , err := manager .Read (ctx , created .GetID ())
67+ if err != nil {
68+ t .Fatalf ("Read failed: %v" , err )
69+ }
70+
71+ if entity .GetID () != created .GetID () {
72+ t .Errorf ("expected ID %d, got %d" , created .GetID (), entity .GetID ())
73+ }
74+
75+ if entity .GetName () != "test-read" {
76+ t .Errorf ("expected name 'test-read', got %s" , entity .GetName ())
77+ }
78+ })
79+
80+ t .Run ("Update" , func (t * testing.T ) {
81+ manager := & testCRUDManager {}
82+
83+ // Create entity first
84+ created , err := manager .Create (ctx , "original-name" )
85+ if err != nil {
86+ t .Fatalf ("Create failed: %v" , err )
87+ }
88+
89+ // Update it
90+ updated , err := manager .Update (ctx , created .GetID (), "updated-name" )
91+ if err != nil {
92+ t .Fatalf ("Update failed: %v" , err )
93+ }
94+
95+ if updated .GetName () != "updated-name" {
96+ t .Errorf ("expected name 'updated-name', got %s" , updated .GetName ())
97+ }
98+
99+ if updated .GetUpdatedAt ().Before (created .GetUpdatedAt ()) {
100+ t .Error ("expected UpdatedAt to be updated" )
101+ }
102+ })
103+
104+ t .Run ("Delete" , func (t * testing.T ) {
105+ manager := & testCRUDManager {}
106+
107+ // Create entity first
108+ created , err := manager .Create (ctx , "to-delete" )
109+ if err != nil {
110+ t .Fatalf ("Create failed: %v" , err )
111+ }
112+
113+ // Delete it
114+ err = manager .Delete (ctx , created .GetID ())
115+ if err != nil {
116+ t .Fatalf ("Delete failed: %v" , err )
117+ }
118+
119+ // Verify it's gone
120+ _ , err = manager .Read (ctx , created .GetID ())
121+ if err == nil {
122+ t .Error ("expected Read to fail after Delete" )
123+ }
124+ })
125+
126+ t .Run ("List" , func (t * testing.T ) {
127+ manager := & testCRUDManager {}
128+
129+ // Create some entities
130+ names := []string {"entity1" , "entity2" , "entity3" }
131+ for _ , name := range names {
132+ _ , err := manager .Create (ctx , name )
133+ if err != nil {
134+ t .Fatalf ("Create failed: %v" , err )
135+ }
136+ }
137+
138+ // List them
139+ entities , err := manager .List (ctx )
140+ if err != nil {
141+ t .Fatalf ("List failed: %v" , err )
142+ }
143+
144+ if len (entities ) < len (names ) {
145+ t .Errorf ("expected at least %d entities, got %d" , len (names ), len (entities ))
146+ }
147+ })
148+ }
149+
150+ func TestCRUDValidation (t * testing.T ) {
151+ ctx := context .Background ()
152+ manager := & testCRUDManager {}
153+
154+ t .Run ("Create with empty name" , func (t * testing.T ) {
155+ _ , err := manager .Create (ctx , "" )
156+ if err == nil {
157+ t .Error ("expected Create with empty name to fail" )
158+ }
159+ })
160+
161+ t .Run ("Read non-existent entity" , func (t * testing.T ) {
162+ _ , err := manager .Read (ctx , 99999 )
163+ if err == nil {
164+ t .Error ("expected Read of non-existent entity to fail" )
165+ }
166+ })
167+
168+ t .Run ("Update non-existent entity" , func (t * testing.T ) {
169+ _ , err := manager .Update (ctx , 99999 , "new-name" )
170+ if err == nil {
171+ t .Error ("expected Update of non-existent entity to fail" )
172+ }
173+ })
174+
175+ t .Run ("Delete non-existent entity" , func (t * testing.T ) {
176+ err := manager .Delete (ctx , 99999 )
177+ if err == nil {
178+ t .Error ("expected Delete of non-existent entity to fail" )
179+ }
180+ })
181+ }
182+
183+ type testCRUDManager struct {
184+ entities map [int64 ]TestEntity
185+ nextID int64
186+ }
187+
188+ func (m * testCRUDManager ) Create (ctx context.Context , name string ) (TestEntity , error ) {
189+ if m .entities == nil {
190+ m .entities = make (map [int64 ]TestEntity )
191+ m .nextID = 1
192+ }
193+
194+ if name == "" {
195+ return TestEntity {}, ErrInvalidInput
196+ }
197+
198+ now := time .Now ()
199+ entity := TestEntity {
200+ ID : m .nextID ,
201+ Name : name ,
202+ CreatedAt : now ,
203+ UpdatedAt : now ,
204+ }
205+
206+ m .entities [m .nextID ] = entity
207+ m .nextID ++
208+
209+ return entity , nil
210+ }
211+
212+ func (m * testCRUDManager ) Read (ctx context.Context , id int64 ) (TestEntity , error ) {
213+ if m .entities == nil {
214+ return TestEntity {}, ErrNotFound
215+ }
216+
217+ entity , exists := m .entities [id ]
218+ if ! exists {
219+ return TestEntity {}, ErrNotFound
220+ }
221+
222+ return entity , nil
223+ }
224+
225+ func (m * testCRUDManager ) Update (ctx context.Context , id int64 , name string ) (TestEntity , error ) {
226+ if m .entities == nil {
227+ return TestEntity {}, ErrNotFound
228+ }
229+
230+ entity , exists := m .entities [id ]
231+ if ! exists {
232+ return TestEntity {}, ErrNotFound
233+ }
234+
235+ if name == "" {
236+ return TestEntity {}, ErrInvalidInput
237+ }
238+
239+ entity .Name = name
240+ entity .UpdatedAt = time .Now ()
241+ m .entities [id ] = entity
242+
243+ return entity , nil
244+ }
245+
246+ func (m * testCRUDManager ) Delete (ctx context.Context , id int64 ) error {
247+ if m .entities == nil {
248+ return ErrNotFound
249+ }
250+
251+ _ , exists := m .entities [id ]
252+ if ! exists {
253+ return ErrNotFound
254+ }
255+
256+ delete (m .entities , id )
257+ return nil
258+ }
259+
260+ func (m * testCRUDManager ) List (ctx context.Context ) ([]TestEntity , error ) {
261+ if m .entities == nil {
262+ return []TestEntity {}, nil
263+ }
264+
265+ entities := make ([]TestEntity , 0 , len (m .entities ))
266+ for _ , entity := range m .entities {
267+ entities = append (entities , entity )
268+ }
269+
270+ return entities , nil
271+ }
0 commit comments