17fc813823
M1, M2 and M3 complete * M1, M2 and M3 complete * review changes * docs * docs
167 lines
5.8 KiB
Go
167 lines
5.8 KiB
Go
//go:build milestone2
|
|
|
|
// Package repository_test — Milestone 2 §2.3 failing SQLC query presence
|
|
// tests.
|
|
//
|
|
// Build tag: gated behind `milestone2` so the default `task fullsuite:ci`
|
|
// run does not execute it. See the comment in milestone2_migrations_test.go
|
|
// for the workflow the golang engineer follows to flip these tests from
|
|
// RED to GREEN.
|
|
//
|
|
// These tests prove that the next batch of SQLC queries required by
|
|
// Milestone 2 (plan Section 6.3 / tracking §2.3) are available on the
|
|
// generated *Queries type once the golang engineer runs `task generate`
|
|
// against a new internal/database/queries/custommetadata.sql query file.
|
|
//
|
|
// They use reflection to introspect the *Queries receiver rather than
|
|
// calling the methods directly so the test file can compile before the
|
|
// queries exist — a hard compile-time reference would break the whole
|
|
// package build and the rest of Milestone 1's tests with it.
|
|
//
|
|
// When the golang engineer adds the new SQL query blocks and re-runs
|
|
// `task generate`, sqlc will emit the corresponding Go methods and
|
|
// these tests will flip from failing to passing without any further
|
|
// edits.
|
|
package repository_test
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"queryorchestration/internal/database/repository"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// milestone2RequiredQueries is the full list of new SQLC-generated
|
|
// method names that §2.3 of the v4 tracking doc requires. Every row
|
|
// maps to a block in the forthcoming internal/database/queries/custommetadata.sql
|
|
// file. The comment after each name traces back to the tracking line.
|
|
//
|
|
// Deliberately NOT in this list (see the "v4" notes in the tracking doc):
|
|
// - DocumentHasLegacyExtractions: reuse existing HasFieldExtraction
|
|
// - DeleteDocumentCustomMetadata: FK cascade replaces it
|
|
// - NullifyDocumentCustomSchemaId: reset-metadata uses a direct UPDATE
|
|
// - DeleteClientMetadataSchemas: FK cascade replaces it
|
|
// - LockDocumentCustomMetadataForVersion: v3 name, replaced by
|
|
// LockDocumentForMetadataWrite
|
|
var milestone2RequiredQueries = []struct {
|
|
method string
|
|
trackRef string
|
|
}{
|
|
{
|
|
method: "CreateDocumentCustomMetadata",
|
|
trackRef: "§2.3 CreateDocumentCustomMetadata (no schema_id parameter)",
|
|
},
|
|
{
|
|
method: "GetCurrentDocumentCustomMetadata",
|
|
trackRef: "§2.3 GetCurrentDocumentCustomMetadata (ORDER BY version DESC LIMIT 1, joins documents + client_metadata_schemas)",
|
|
},
|
|
{
|
|
method: "GetDocumentCustomMetadataByVersion",
|
|
trackRef: "§2.3 GetDocumentCustomMetadataByVersion (same join)",
|
|
},
|
|
{
|
|
method: "GetDocumentCustomMetadataHistory",
|
|
trackRef: "§2.3 GetDocumentCustomMetadataHistory (no schema join)",
|
|
},
|
|
{
|
|
method: "LockDocumentForMetadataWrite",
|
|
trackRef: "§2.3 LockDocumentForMetadataWrite (parent-row lock replacing v3's LockDocumentCustomMetadataForVersion)",
|
|
},
|
|
{
|
|
method: "GetMaxDocumentMetadataVersion",
|
|
trackRef: "§2.3 GetMaxDocumentMetadataVersion (COALESCE(MAX(version), 0))",
|
|
},
|
|
{
|
|
method: "SetDocumentCustomSchemaId",
|
|
trackRef: "§2.3 SetDocumentCustomSchemaId",
|
|
},
|
|
{
|
|
method: "GetDocumentCustomSchemaId",
|
|
trackRef: "§2.3 GetDocumentCustomSchemaId",
|
|
},
|
|
}
|
|
|
|
// TestMilestone2_RequiredSQLCQueries asserts every method in
|
|
// milestone2RequiredQueries is present on the generated *repository.Queries
|
|
// type. Uses reflection so this file compiles even before the query file
|
|
// lands — a hard Go reference would break the whole test binary and
|
|
// every other Milestone 1 test with it.
|
|
//
|
|
// This test FAILS intentionally until the golang engineer adds the query
|
|
// blocks to internal/database/queries/custommetadata.sql and runs
|
|
// `task generate`.
|
|
func TestMilestone2_RequiredSQLCQueries(t *testing.T) {
|
|
t.Parallel()
|
|
// No DB needed — this is a pure type-introspection check.
|
|
// We still run under short mode since the assertion is a static
|
|
// shape check and should be part of the fast unit sweep.
|
|
|
|
var q repository.Queries
|
|
qType := reflect.TypeOf(&q)
|
|
|
|
for _, want := range milestone2RequiredQueries {
|
|
want := want
|
|
t.Run(want.method, func(t *testing.T) {
|
|
t.Parallel()
|
|
_, ok := qType.MethodByName(want.method)
|
|
require.Truef(t, ok,
|
|
"generated *repository.Queries must have method %q — source of truth: %s. "+
|
|
"Add the SQL block to internal/database/queries/custommetadata.sql and run `task generate`.",
|
|
want.method, want.trackRef)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestMilestone2_RemovedV3QueriesAbsent asserts the v3 query names that
|
|
// v4 deliberately dropped never sneak back into the generated code. If a
|
|
// future contributor copies a v3 snippet into custommetadata.sql these
|
|
// assertions will fail loudly with a pointer to the tracking doc's
|
|
// "v4 removed" notes.
|
|
func TestMilestone2_RemovedV3QueriesAbsent(t *testing.T) {
|
|
t.Parallel()
|
|
forbidden := []struct {
|
|
method string
|
|
why string
|
|
}{
|
|
{
|
|
method: "DocumentHasLegacyExtractions",
|
|
why: "v4 reuses existing HasFieldExtraction — see §2.3 'Reuse existing query'",
|
|
},
|
|
{
|
|
method: "DeleteDocumentCustomMetadata",
|
|
why: "v4 relies on ON DELETE CASCADE via the document_id FK",
|
|
},
|
|
{
|
|
method: "NullifyDocumentCustomSchemaId",
|
|
why: "v4 resets via direct UPDATE documents SET custom_schema_id = NULL",
|
|
},
|
|
{
|
|
method: "DeleteClientMetadataSchemas",
|
|
why: "v4 relies on ON DELETE CASCADE via the client_id FK",
|
|
},
|
|
{
|
|
method: "LockDocumentCustomMetadataForVersion",
|
|
why: "v4 uses LockDocumentForMetadataWrite (parent-row lock) instead",
|
|
},
|
|
{
|
|
method: "GetSchemaMetadataRecordCount",
|
|
why: "v4 computes canDelete from GetSchemaDocumentCount alone",
|
|
},
|
|
}
|
|
|
|
var q repository.Queries
|
|
qType := reflect.TypeOf(&q)
|
|
for _, bad := range forbidden {
|
|
bad := bad
|
|
t.Run(bad.method, func(t *testing.T) {
|
|
t.Parallel()
|
|
_, ok := qType.MethodByName(bad.method)
|
|
require.Falsef(t, ok,
|
|
"*repository.Queries must NOT have method %q — %s",
|
|
bad.method, bad.why)
|
|
})
|
|
}
|
|
}
|