Skip to content

Commit c71d6bc

Browse files
Use GetTransaction for unit-testing transaction based context (#62)
Fixes #49
1 parent 34094f9 commit c71d6bc

File tree

6 files changed

+115
-31
lines changed

6 files changed

+115
-31
lines changed

docs/DOCUMENTATION.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ func main() {
668668

669669
// Initializes the Datastore using the metadata authorizer and connection details obtained from the ENV variables.
670670
ds, err := datastore.FromEnvWithDB(datastore.GetCompLogger(), mdAuthorizer, instancer, "ExampleDataStore_multiInstance")
671+
defer ds.Reset()
671672
if err != nil {
672673
log.Fatalf("datastore initialization from env errored: %s", err)
673674
}
@@ -787,6 +788,7 @@ func main() {
787788

788789
// Initializes the Datastore using the metadata authorizer and connection details obtained from the ENV variables.
789790
ds, err := datastore.FromEnvWithDB(datastore.GetCompLogger(), mdAuthorizer, nil, "ExampleDataStore_multiTenancy")
791+
defer ds.Reset()
790792
if err != nil {
791793
log.Fatalf("datastore initialization from env errored: %s", err)
792794
}
@@ -1417,6 +1419,7 @@ func main() {
14171419
myLogger := datastore.GetCompLogger()
14181420
mdAuthorizer := authorizer.MetadataBasedAuthorizer{}
14191421
myDatastore, _ := datastore.FromEnvWithDB(myLogger, mdAuthorizer, nil, "ExampleProtoStore")
1422+
defer myDatastore.Reset()
14201423
ctx := mdAuthorizer.GetAuthContext("Coke", "service_admin")
14211424
myProtostore := protostore.GetProtoStore(myLogger, myDatastore)
14221425

pkg/datastore/datastore_with_txcontext_test.go

Lines changed: 108 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,27 @@ func rollbackTx(t *testing.T, tx *gorm.DB) {
4141
}
4242
}
4343

44-
func testTxCrud(t *testing.T, ds datastore.DataStore, ctx context.Context, myCokeApp *App, user1, user2 *AppUser) {
44+
func testTxCrud(t *testing.T, ds datastore.DataStore, ctx context.Context, user1, user2 *AppUser) {
4545
t.Helper()
4646
assert := assert.New(t)
4747
var err error
4848

4949
txFetcher := authorizer.SimpleTransactionFetcher{}
5050

51-
// Querying of previously inserted records should succeed
51+
t.Log("Querying created records in single transaction")
52+
tx, err := ds.GetTransaction(ctx, user1)
53+
assert.NoError(err)
54+
defer rollbackTx(t, tx)
55+
txCtx := txFetcher.WithTransactionCtx(ctx, tx)
5256
for _, record := range []*AppUser{user1, user2} {
5357
queryResult := AppUser{Id: record.Id}
54-
err = ds.Find(ctx, &queryResult)
58+
err = ds.Find(txCtx, &queryResult)
5559
assert.NoError(err)
5660
assert.Equal(record, &queryResult)
5761
}
62+
assert.NoError(tx.Commit().Error)
5863

59-
// Updating non-key fields in a record should succeed
64+
t.Log("Verifying update and find in single transaction")
6065
user1.Name = "Jeyhun G."
6166
user1.Email = "jeyhun111@mail.com"
6267
user1.EmailConfirmed = !user1.EmailConfirmed
@@ -65,58 +70,56 @@ func testTxCrud(t *testing.T, ds datastore.DataStore, ctx context.Context, myCok
6570
user2.Email = "jahangir111@mail.com"
6671
user2.EmailConfirmed = !user2.EmailConfirmed
6772
user2.NumFollowers--
68-
69-
// TODO: Find, Update and Delete are still not supported due to appending where clauses,
70-
// after each call to Find/Update/Delete methods
71-
72-
tx, err := ds.Helper().GetDBTransaction(ctx, datastore.GetTableName(user1), user1)
73+
tx, err = ds.GetTransaction(ctx, user1)
7374
assert.NoError(err)
7475
defer rollbackTx(t, tx)
75-
txCtx := txFetcher.WithTransactionCtx(ctx, tx)
76+
txCtx = txFetcher.WithTransactionCtx(ctx, tx)
7677
for _, record := range []*AppUser{user1, user2} {
77-
rowsAffected, err := ds.Upsert(txCtx, record)
78+
rowsAffected, err := ds.Update(txCtx, record)
7879
assert.NoError(err)
7980
assert.EqualValues(1, rowsAffected)
80-
}
81-
assert.NoError(tx.Commit().Error)
8281

83-
for _, record := range []*AppUser{user1, user2} {
8482
queryResult := &AppUser{Id: record.Id}
85-
err = ds.Find(ctx, queryResult)
83+
err = ds.Find(txCtx, queryResult)
8684
assert.NoError(err)
8785
assert.Equal(record, queryResult)
8886
}
87+
assert.NoError(tx.Commit().Error)
8988

90-
tx, err = ds.Helper().GetDBTransaction(ctx, datastore.GetTableName(user1), user1)
89+
t.Log("Verifying upsert and find in single transaction")
90+
user1.NumFollowers++
91+
user2.NumFollowers--
92+
tx, err = ds.GetTransaction(ctx, user1)
9193
assert.NoError(err)
9294
defer rollbackTx(t, tx)
9395
txCtx = txFetcher.WithTransactionCtx(ctx, tx)
94-
// Upsert operation should be an update for already existing records
95-
user1.NumFollowers++
96-
user2.NumFollowers--
9796
for _, record := range []*AppUser{user1, user2} {
9897
rowsAffected, err := ds.Upsert(txCtx, record)
9998
assert.NoError(err)
10099
assert.EqualValues(1, rowsAffected)
101-
}
102-
assert.NoError(tx.Commit().Error)
103-
for _, record := range []*AppUser{user1, user2} {
100+
104101
queryResult := &AppUser{Id: record.Id}
105-
err = ds.Find(ctx, queryResult)
102+
err = ds.Find(txCtx, queryResult)
106103
assert.NoError(err)
107104
assert.Equal(record, queryResult)
108105
}
106+
assert.NoError(tx.Commit().Error)
109107

110-
// Deletion of existing records should not fail, and the records should no longer be found in the DB
108+
t.Log("Verifying deletion and find in single transaction")
109+
tx, err = ds.GetTransaction(ctx, user1)
110+
assert.NoError(err)
111+
defer rollbackTx(t, tx)
112+
txCtx = txFetcher.WithTransactionCtx(ctx, tx)
111113
for _, record := range []*AppUser{user1, user2} {
112-
rowsAffected, err := ds.Delete(ctx, record)
114+
rowsAffected, err := ds.Delete(txCtx, record)
113115
assert.NoError(err)
114116
assert.EqualValues(1, rowsAffected)
115117
queryResult := AppUser{Id: record.Id}
116-
err = ds.Find(ctx, &queryResult)
118+
err = ds.Find(txCtx, &queryResult)
117119
assert.ErrorIs(err, ErrRecordNotFound)
118120
assert.True(queryResult.AreNonKeyFieldsEmpty())
119121
}
122+
assert.NoError(tx.Commit().Error)
120123
}
121124

122125
func BenchmarkTxCrud(b *testing.B) {
@@ -126,17 +129,91 @@ func BenchmarkTxCrud(b *testing.B) {
126129
LOG = logger.WithField(datastore.COMP, datastore.SAAS_PERSISTENCE)
127130

128131
var t testing.T
129-
ds, _ := SetupDataStore("BenchmarkCrud")
132+
ds, _ := SetupDataStore("BenchmarkTxCrud")
130133
defer ds.Reset()
131-
myCokeApp, user1, user2 := SetupDbTables(ds)
134+
_, user1, user2 := SetupDbTables(ds)
132135
for n := 0; n < b.N; n++ {
133-
testCrud(&t, ds, CokeAdminCtx, myCokeApp, user1, user2)
136+
testTxCrud(&t, ds, CokeAdminCtx, user1, user2)
134137
}
135138
}
136139

137140
func TestTxCrud(t *testing.T) {
138141
ds, _ := SetupDataStore("TestTxCrud")
139142
defer ds.Reset()
140-
myCokeApp, user1, user2 := SetupDbTables(ds)
141-
testTxCrud(t, ds, CokeAdminCtx, myCokeApp, user1, user2)
143+
_, user1, user2 := SetupDbTables(ds)
144+
testTxCrud(t, ds, CokeAdminCtx, user1, user2)
145+
}
146+
147+
func TestSingleTxCrud(t *testing.T) {
148+
assert := assert.New(t)
149+
var err error
150+
151+
ctx := CokeAdminCtx
152+
ds, _ := SetupDataStore("TestSingleTxCrud")
153+
defer ds.Reset()
154+
_, user1, user2 := SetupDbTables(ds)
155+
156+
txFetcher := authorizer.SimpleTransactionFetcher{}
157+
tx, err := ds.GetTransaction(ctx, user1)
158+
assert.NoError(err)
159+
defer rollbackTx(t, tx)
160+
txCtx := txFetcher.WithTransactionCtx(ctx, tx)
161+
162+
t.Log("Querying created records in same transaction")
163+
for _, record := range []*AppUser{user1, user2} {
164+
queryResult := AppUser{Id: record.Id}
165+
err = ds.Find(txCtx, &queryResult)
166+
assert.NoError(err)
167+
assert.Equal(record, &queryResult)
168+
}
169+
170+
t.Log("Verifying update and find in same transaction")
171+
user1.Name = "Jeyhun G."
172+
user1.Email = "jeyhun111@mail.com"
173+
user1.EmailConfirmed = !user1.EmailConfirmed
174+
user1.NumFollowers++
175+
user2.Name = "Jahangir G."
176+
user2.Email = "jahangir111@mail.com"
177+
user2.EmailConfirmed = !user2.EmailConfirmed
178+
user2.NumFollowers--
179+
tx, err = ds.GetTransaction(ctx, user1)
180+
assert.NoError(err)
181+
defer rollbackTx(t, tx)
182+
txCtx = txFetcher.WithTransactionCtx(ctx, tx)
183+
for _, record := range []*AppUser{user1, user2} {
184+
rowsAffected, err := ds.Update(txCtx, record)
185+
assert.NoError(err)
186+
assert.EqualValues(1, rowsAffected)
187+
188+
queryResult := &AppUser{Id: record.Id}
189+
err = ds.Find(txCtx, queryResult)
190+
assert.NoError(err)
191+
assert.Equal(record, queryResult)
192+
}
193+
194+
t.Log("Verifying upsert and find in same transaction")
195+
user1.NumFollowers++
196+
user2.NumFollowers--
197+
for _, record := range []*AppUser{user1, user2} {
198+
rowsAffected, err := ds.Upsert(txCtx, record)
199+
assert.NoError(err)
200+
assert.EqualValues(1, rowsAffected)
201+
202+
queryResult := &AppUser{Id: record.Id}
203+
err = ds.Find(txCtx, queryResult)
204+
assert.NoError(err)
205+
assert.Equal(record, queryResult)
206+
}
207+
208+
t.Log("Verifying deletion and find in same transaction")
209+
for _, record := range []*AppUser{user1, user2} {
210+
rowsAffected, err := ds.Delete(txCtx, record)
211+
assert.NoError(err)
212+
assert.EqualValues(1, rowsAffected)
213+
queryResult := AppUser{Id: record.Id}
214+
err = ds.Find(txCtx, &queryResult)
215+
assert.ErrorIs(err, ErrRecordNotFound)
216+
assert.True(queryResult.AreNonKeyFieldsEmpty())
217+
}
218+
assert.NoError(tx.Commit().Error)
142219
}

pkg/datastore/example_multiinstance_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func ExampleDataStore_multiInstance() {
4040

4141
// Initializes the Datastore using the metadata authorizer and connection details obtained from the ENV variables.
4242
ds, err := datastore.FromEnvWithDB(datastore.GetCompLogger(), mdAuthorizer, instancer, "ExampleDataStore_multiInstance")
43+
defer ds.Reset()
4344
if err != nil {
4445
log.Fatalf("datastore initialization from env errored: %s", err)
4546
}

pkg/datastore/example_multitenancy_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func ExampleDataStore_multiTenancy() {
3737

3838
// Initializes the Datastore using the metadata authorizer and connection details obtained from the ENV variables.
3939
ds, err := datastore.FromEnvWithDB(datastore.GetCompLogger(), mdAuthorizer, nil, "ExampleDataStore_multiTenancy")
40+
defer ds.Reset()
4041
if err != nil {
4142
log.Fatalf("datastore initialization from env errored: %s", err)
4243
}

pkg/datastore/noinstancer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func TestDataStoreWithoutInstancer(t *testing.T) {
4242
ProdInstanceCtx := instancer.WithInstanceId(ServiceAdminCtx, "Prod")
4343

4444
ds, _ := datastore.FromEnv(datastore.GetCompLogger(), mdAuthorizer, nil)
45+
defer ds.Reset()
4546
roleMapping := map[string]dbrole.DbRole{
4647
SERVICE_AUDITOR: dbrole.READER,
4748
SERVICE_ADMIN: dbrole.WRITER,

pkg/protostore/example_protostore_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ func ExampleProtoStore() {
1616
myLogger := datastore.GetCompLogger()
1717
mdAuthorizer := authorizer.MetadataBasedAuthorizer{}
1818
myDatastore, _ := datastore.FromEnvWithDB(myLogger, mdAuthorizer, nil, "ExampleProtoStore")
19+
defer myDatastore.Reset()
1920
ctx := mdAuthorizer.GetAuthContext("Coke", "service_admin")
2021
myProtostore := protostore.GetProtoStore(myLogger, myDatastore)
2122

0 commit comments

Comments
 (0)