package browse import ( "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // tableHash is a helper for the common "the table must exist here" case. func tableHash(t *testing.T, db *DB, ctx context.Context, refStr, table string) string { t.Helper() h, ok, err := db.TableHash(ctx, refStr, table) require.NoError(t, err) require.True(t, ok, "table %q must exist at %q", table, refStr) require.NotEmpty(t, h) return h } func TestTableHashStable(t *testing.T) { db := openFixture(t) ctx := context.Background() first := tableHash(t, db, ctx, "main", "users") second := tableHash(t, db, ctx, "main", "users") assert.Equal(t, first, second, "the same table at the same ref must hash the same") // A branch and the commit hash it points at are the same root, so they must // produce the same table hash. dev's head is C2. byBranch := tableHash(t, db, ctx, "dev", "users") byCommit := tableHash(t, db, ctx, commitHash(t, msgInsert), "users") assert.Equal(t, byBranch, byCommit, "branch and its head commit must agree") } // TestTableHashDetectsChange is the property the whole history walk rests on: // the hash changes exactly when the table does. func TestTableHashDetectsChange(t *testing.T) { db := openFixture(t) ctx := context.Background() atInsert := tableHash(t, db, ctx, commitHash(t, msgInsert), "users") // C2 atModify := tableHash(t, db, ctx, commitHash(t, msgModify), "users") // C3: rows changed atAddItem := tableHash(t, db, ctx, commitHash(t, msgAddItem), "users") assert.NotEqual(t, atInsert, atModify, "C3 changed users rows, hash must differ") // C4 created items and docs and left users alone: a walk must be able to // skip it without reading a row. assert.Equal(t, atAddItem, atModify, "C4 did not touch users, hash must be unchanged") } func TestTableHashMissingTable(t *testing.T) { db := openFixture(t) ctx := context.Background() // items is created by C4, so it does not exist at C2 — an ordinary answer // for a backwards walk, not an error. h, ok, err := db.TableHash(ctx, commitHash(t, msgInsert), "items") require.NoError(t, err) assert.False(t, ok) assert.Empty(t, h) // A table that never existed behaves the same way. h, ok, err = db.TableHash(ctx, "main", "no-such-table") require.NoError(t, err) assert.False(t, ok) assert.Empty(t, h) } func TestTableHashRefNotFound(t *testing.T) { db := openFixture(t) ctx := context.Background() _, ok, err := db.TableHash(ctx, "no-such-ref", "users") require.ErrorIs(t, err, ErrRefNotFound) assert.False(t, ok) } func TestTableHashDistinctTables(t *testing.T) { db := openFixture(t) ctx := context.Background() users := tableHash(t, db, ctx, "main", "users") items := tableHash(t, db, ctx, "main", "items") docs := tableHash(t, db, ctx, "main", "docs") assert.NotEqual(t, users, items) assert.NotEqual(t, users, docs) assert.NotEqual(t, items, docs, "an empty table must not collide with another table") }