Skip to content

Commit baaee98

Browse files
committed
fix: add schema mode verification to UnifiedSchemaHash test
- Add SchemaModeForTesting() method to all datastores returning (SchemaMode, error) - Add SchemaModeForTesting() to indexcheck and relationshipintegrity proxies - Update UnifiedSchemaHashTest to explicitly check schema mode from datastore - Test now correctly validates: - Hash is NOT written in ReadLegacyWriteLegacy mode - Hash IS written and correct in ReadLegacyWriteBoth, ReadNewWriteBoth, ReadNewWriteNew - Test fails explicitly if datastore doesn't implement SchemaModeForTesting() - Fixes test failures in default mode for MySQL, CRDB, and Spanner
1 parent 0cff0d2 commit baaee98

File tree

8 files changed

+106
-15
lines changed

8 files changed

+106
-15
lines changed

internal/datastore/crdb/crdb.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,11 @@ func (cds *crdbDatastore) SchemaHashWatcherForTesting() datastore.SingleStoreSch
550550
return newCRDBSchemaHashWatcher(cds.readPool, schemaChangefeedFormat)
551551
}
552552

553+
// SchemaModeForTesting returns the current schema mode for testing purposes.
554+
func (cds *crdbDatastore) SchemaModeForTesting() (options.SchemaMode, error) {
555+
return cds.schemaMode, nil
556+
}
557+
553558
type crdbSchemaHashReaderForTesting struct {
554559
query *pool.RetryPool
555560
}

internal/datastore/memdb/memdb.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,12 @@ func (mdb *memdbDatastore) SchemaHashWatcherForTesting() datastore.SingleStoreSc
426426
return newMemdbSchemaHashWatcher(mdb)
427427
}
428428

429+
// SchemaModeForTesting returns the current schema mode for testing purposes.
430+
// MemDB always operates in a mode equivalent to ReadNewWriteNew.
431+
func (mdb *memdbDatastore) SchemaModeForTesting() (options.SchemaMode, error) {
432+
return options.SchemaModeReadNewWriteNew, nil
433+
}
434+
429435
type memdbSchemaHashReaderForTesting struct {
430436
db *memdbDatastore
431437
}

internal/datastore/mysql/datastore.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,11 @@ func (mds *mysqlDatastore) SchemaHashWatcherForTesting() datastore.SingleStoreSc
597597
return newMySQLSchemaHashWatcher(mds.db, mds.driver.SchemaRevision())
598598
}
599599

600+
// SchemaModeForTesting returns the current schema mode for testing purposes.
601+
func (mds *mysqlDatastore) SchemaModeForTesting() (dsoptions.SchemaMode, error) {
602+
return mds.schemaMode, nil
603+
}
604+
600605
type mysqlSchemaHashReaderForTesting struct {
601606
db *sql.DB
602607
schemaRevisionTableName string

internal/datastore/postgres/postgres.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,11 @@ func (pgd *pgDatastore) SchemaHashWatcherForTesting() datastore.SingleStoreSchem
705705
return newPGSchemaHashWatcher(queryFuncs)
706706
}
707707

708+
// SchemaModeForTesting returns the current schema mode for testing purposes.
709+
func (pgd *pgDatastore) SchemaModeForTesting() (dsoptions.SchemaMode, error) {
710+
return pgd.schemaMode, nil
711+
}
712+
708713
type pgSchemaHashReaderForTesting struct {
709714
query pgxcommon.DBFuncQuerier
710715
}

internal/datastore/proxy/indexcheck/indexcheck.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,19 @@ func (p *indexcheckingProxy) SchemaHashWatcherForTesting() datastore.SingleStore
129129
return nil
130130
}
131131

132+
// SchemaModeForTesting returns the current schema mode for testing purposes.
133+
// This delegates to the underlying datastore if it supports the test interface.
134+
func (p *indexcheckingProxy) SchemaModeForTesting() (options.SchemaMode, error) {
135+
type schemaModeProvider interface {
136+
SchemaModeForTesting() (options.SchemaMode, error)
137+
}
138+
139+
if provider, ok := p.delegate.(schemaModeProvider); ok {
140+
return provider.SchemaModeForTesting()
141+
}
142+
return options.SchemaModeReadLegacyWriteLegacy, fmt.Errorf("delegate datastore does not implement SchemaModeForTesting()")
143+
}
144+
132145
type indexcheckingReader struct {
133146
parent datastore.SQLDatastore
134147
delegate datastore.Reader

internal/datastore/proxy/relationshipintegrity.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,31 @@ func (r *relationshipIntegrityProxy) SchemaHashWatcherForTesting() datastore.Sin
357357
return nil
358358
}
359359

360+
// SchemaModeForTesting returns the current schema mode for testing purposes.
361+
// This delegates to the underlying datastore if it supports the test interface.
362+
func (r *relationshipIntegrityProxy) SchemaModeForTesting() (options.SchemaMode, error) {
363+
type provider interface {
364+
SchemaModeForTesting() (options.SchemaMode, error)
365+
}
366+
367+
// Check delegate directly
368+
if p, ok := r.ds.(provider); ok {
369+
return p.SchemaModeForTesting()
370+
}
371+
372+
// Try unwrapping if delegate is itself a proxy
373+
type unwrapper interface {
374+
Unwrap() datastore.Datastore
375+
}
376+
if u, ok := r.ds.(unwrapper); ok {
377+
if p, ok := u.Unwrap().(provider); ok {
378+
return p.SchemaModeForTesting()
379+
}
380+
}
381+
382+
return options.SchemaModeReadLegacyWriteLegacy, fmt.Errorf("delegate datastore does not implement SchemaModeForTesting()")
383+
}
384+
360385
func (r *relationshipIntegrityProxy) Unwrap() datastore.Datastore {
361386
return r.ds
362387
}

internal/datastore/spanner/spanner.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,11 @@ func (sd *spannerDatastore) SchemaHashWatcherForTesting() datastore.SingleStoreS
491491
return newSpannerSchemaHashWatcher(sd.client)
492492
}
493493

494+
// SchemaModeForTesting returns the current schema mode for testing purposes.
495+
func (sd *spannerDatastore) SchemaModeForTesting() (dsoptions.SchemaMode, error) {
496+
return sd.schemaMode, nil
497+
}
498+
494499
type spannerSchemaHashReaderForTesting struct {
495500
client *spanner.Client
496501
}

pkg/datastore/test/unifiedschema.go

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -954,15 +954,34 @@ func UnifiedSchemaHashTest(t *testing.T, tester DatastoreTester) {
954954
})
955955
require.NoError(err)
956956

957+
// Get the schema mode from the datastore to determine expected behavior
958+
schemaModeProvider, ok := ds.(interface {
959+
SchemaModeForTesting() (options.SchemaMode, error)
960+
})
961+
require.True(ok, "datastore must implement SchemaModeForTesting() for this test")
962+
schemaMode, err := schemaModeProvider.SchemaModeForTesting()
963+
require.NoError(err, "failed to get schema mode from datastore")
964+
965+
// Determine if this mode should write the unified schema hash
966+
// The hash is written in all modes that write to the unified schema
967+
shouldWriteHash := schemaMode == options.SchemaModeReadLegacyWriteBoth ||
968+
schemaMode == options.SchemaModeReadNewWriteBoth ||
969+
schemaMode == options.SchemaModeReadNewWriteNew
970+
957971
// Read the schema hash from schema_revision table
958-
hash, err := readerImpl.ReadSchemaHash(ctx)
959-
require.NoError(err)
960-
require.NotEmpty(hash, "schema hash should not be empty")
972+
hash, hashErr := readerImpl.ReadSchemaHash(ctx)
961973

962-
// Verify the hash is correct by computing the expected hash
963-
// The hash is computed from sorted definitions (matching datastore behavior)
964-
expectedHash := computeExpectedSchemaHash(t, testSchemaDefinitions)
965-
require.Equal(expectedHash, hash, "schema hash should match computed hash of sorted schema text")
974+
if shouldWriteHash {
975+
// Hash MUST be present and correct
976+
require.NoError(hashErr, "schema hash should be present in mode %s", schemaMode)
977+
require.NotEmpty(hash, "schema hash should not be empty")
978+
expectedHash := computeExpectedSchemaHash(t, testSchemaDefinitions)
979+
require.Equal(expectedHash, hash, "schema hash should match computed hash of sorted schema text")
980+
} else {
981+
// Hash should NOT be present in ReadLegacyWriteLegacy mode
982+
require.True(errors.Is(hashErr, datastore.ErrSchemaNotFound),
983+
"expected ErrSchemaNotFound in mode %s, got: %v", schemaMode, hashErr)
984+
}
966985

967986
// Update the schema
968987
updatedSchemaText, _, err := generator.GenerateSchema(updatedSchemaDefinitions)
@@ -982,15 +1001,23 @@ func UnifiedSchemaHashTest(t *testing.T, tester DatastoreTester) {
9821001
})
9831002
require.NoError(err)
9841003

985-
// Read the updated schema hash
986-
updatedHash, err := hashReader.SchemaHashReaderForTesting().ReadSchemaHash(ctx)
987-
require.NoError(err)
988-
require.NotEmpty(updatedHash, "updated schema hash should not be empty")
989-
require.NotEqual(hash, updatedHash, "schema hash should change after update")
1004+
// Read the updated schema hash and verify based on mode
1005+
updatedHash, updatedHashErr := hashReader.SchemaHashReaderForTesting().ReadSchemaHash(ctx)
9901006

991-
// Verify the updated hash is correct by computing the expected hash
992-
expectedUpdatedHash := computeExpectedSchemaHash(t, updatedSchemaDefinitions)
993-
require.Equal(expectedUpdatedHash, updatedHash, "updated schema hash should match computed hash of sorted updated schema text")
1007+
if shouldWriteHash {
1008+
// Hash MUST be present, correct, and different from the first hash
1009+
require.NoError(updatedHashErr, "updated schema hash should be present in mode %s", schemaMode)
1010+
require.NotEmpty(updatedHash, "updated schema hash should not be empty")
1011+
require.NotEqual(hash, updatedHash, "schema hash should change after update")
1012+
1013+
// Verify the updated hash is correct
1014+
expectedUpdatedHash := computeExpectedSchemaHash(t, updatedSchemaDefinitions)
1015+
require.Equal(expectedUpdatedHash, updatedHash, "updated schema hash should match computed hash of sorted updated schema text")
1016+
} else {
1017+
// Hash should still NOT be present in ReadLegacyWriteLegacy mode
1018+
require.True(errors.Is(updatedHashErr, datastore.ErrSchemaNotFound),
1019+
"expected ErrSchemaNotFound after update in mode %s, got: %v", schemaMode, updatedHashErr)
1020+
}
9941021
}
9951022

9961023
// UnifiedSchemaHashWatchTest tests the schema hash watcher functionality

0 commit comments

Comments
 (0)