Skip to content

Commit 678b19c

Browse files
committed
✅ test: add Go integration tests for encrypted struct scanning
Add TestPgxInsertEncryptedWithStructScan and TestPgxInsertEncryptedWithJsonbStructScan to test INSERT RETURNING with encrypted columns using struct field scanning. Tests verify encryption/decryption works correctly when populating struct fields directly from database results, specifically targeting JSONB encrypted type issues.
1 parent d7bf1f1 commit 678b19c

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

tests/integration/golang/pgx_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,88 @@ func TestPgxInsertEncryptedWithDomainTypeAndReturning(t *testing.T) {
220220
}
221221
}
222222

223+
// EncryptedRow represents a row with id and encrypted_text fields
224+
type EncryptedRow struct {
225+
ID int `db:"id"`
226+
EncryptedText string `db:"encrypted_text"`
227+
}
228+
229+
// Scan implements the sql.Scanner interface for EncryptedRow
230+
func (er *EncryptedRow) Scan(src interface{}) error {
231+
return fmt.Errorf("Scan method not implemented for single value")
232+
}
233+
234+
func TestPgxInsertEncryptedWithStructScan(t *testing.T) {
235+
t.Parallel()
236+
conn := setupPgxConnection(t)
237+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
238+
defer cancel()
239+
240+
tx, err := conn.Begin(ctx)
241+
require.NoError(t, err)
242+
defer tx.Rollback(ctx)
243+
244+
encryptedTextValue := "test encrypted content"
245+
insertStmt := `INSERT INTO encrypted (id, encrypted_text) VALUES ($1, $2) RETURNING id, encrypted_text`
246+
247+
for _, mode := range modes {
248+
id := rand.Int()
249+
250+
t.Run(mode.String(), func(t *testing.T) {
251+
t.Run("insert_with_struct_scan", func(t *testing.T) {
252+
var row EncryptedRow
253+
err := conn.QueryRow(context.Background(), insertStmt, mode, id, encryptedTextValue).Scan(&row.ID, &row.EncryptedText)
254+
require.NoError(t, err)
255+
require.Equal(t, id, row.ID)
256+
require.Equal(t, encryptedTextValue, row.EncryptedText)
257+
})
258+
})
259+
}
260+
}
261+
262+
// EncryptedRowWithJsonb represents a row with id, encrypted_text and encrypted_jsonb fields
263+
type EncryptedRowWithJsonb struct {
264+
ID int `db:"id"`
265+
EncryptedText string `db:"encrypted_text"`
266+
EncryptedJsonb map[string]interface{} `db:"encrypted_jsonb"`
267+
}
268+
269+
// Scan implements the sql.Scanner interface for EncryptedRowWithJsonb
270+
func (er *EncryptedRowWithJsonb) Scan(src interface{}) error {
271+
return fmt.Errorf("Scan method not implemented for single value")
272+
}
273+
274+
func TestPgxInsertEncryptedWithJsonbStructScan(t *testing.T) {
275+
t.Parallel()
276+
conn := setupPgxConnection(t)
277+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
278+
defer cancel()
279+
280+
tx, err := conn.Begin(ctx)
281+
require.NoError(t, err)
282+
defer tx.Rollback(ctx)
283+
284+
encryptedTextValue := "test encrypted content"
285+
encryptedJsonbValue := `{"key":"value","number":42}`
286+
expectedJsonbValue := map[string]interface{}{
287+
"key": "value",
288+
"number": float64(42),
289+
}
290+
insertStmt := `INSERT INTO encrypted (id, encrypted_text, encrypted_jsonb) VALUES ($1, $2, $3) RETURNING id, encrypted_text, encrypted_jsonb`
291+
292+
for _, mode := range modes {
293+
id := rand.Int()
294+
295+
t.Run(mode.String(), func(t *testing.T) {
296+
t.Run("insert_with_jsonb_struct_scan", func(t *testing.T) {
297+
var row EncryptedRowWithJsonb
298+
err := conn.QueryRow(context.Background(), insertStmt, mode, id, encryptedTextValue, encryptedJsonbValue).Scan(&row.ID, &row.EncryptedText, &row.EncryptedJsonb)
299+
require.NoError(t, err)
300+
require.Equal(t, id, row.ID)
301+
require.Equal(t, encryptedTextValue, row.EncryptedText)
302+
require.Equal(t, expectedJsonbValue, row.EncryptedJsonb)
303+
})
304+
})
305+
}
306+
}
307+

0 commit comments

Comments
 (0)