496 lines
12 KiB
Go
496 lines
12 KiB
Go
package dctx
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
|
"git.warky.dev/wdevs/relspecgo/pkg/readers"
|
|
)
|
|
|
|
func TestReader_ReadDatabase(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
db, err := reader.ReadDatabase()
|
|
if err != nil {
|
|
t.Fatalf("ReadDatabase() error = %v", err)
|
|
}
|
|
|
|
if db == nil {
|
|
t.Fatal("ReadDatabase() returned nil database")
|
|
}
|
|
|
|
if db.Name == "" {
|
|
t.Error("Expected non-empty database name")
|
|
}
|
|
|
|
if len(db.Schemas) == 0 {
|
|
t.Fatal("Expected at least one schema")
|
|
}
|
|
|
|
schema := db.Schemas[0]
|
|
if schema.Name == "" {
|
|
t.Error("Expected non-empty schema name")
|
|
}
|
|
|
|
if len(schema.Tables) == 0 {
|
|
t.Fatal("Expected at least one table")
|
|
}
|
|
|
|
// Verify at least one table has columns
|
|
hasColumns := false
|
|
for _, table := range schema.Tables {
|
|
if len(table.Columns) > 0 {
|
|
hasColumns = true
|
|
break
|
|
}
|
|
}
|
|
if !hasColumns {
|
|
t.Error("Expected at least one table with columns")
|
|
}
|
|
|
|
// Verify at least one table has a primary key
|
|
hasPK := false
|
|
for _, table := range schema.Tables {
|
|
pk := table.GetPrimaryKey()
|
|
if pk != nil {
|
|
hasPK = true
|
|
break
|
|
}
|
|
}
|
|
if !hasPK {
|
|
t.Error("Expected at least one table with a primary key")
|
|
}
|
|
|
|
// Verify at least one foreign key relationship exists
|
|
hasFKs := false
|
|
for _, table := range schema.Tables {
|
|
fks := table.GetForeignKeys()
|
|
if len(fks) > 0 {
|
|
hasFKs = true
|
|
// Verify foreign key properties
|
|
for _, fk := range fks {
|
|
if fk.Type != models.ForeignKeyConstraint {
|
|
t.Error("Expected foreign key constraint type")
|
|
}
|
|
if len(fk.Columns) == 0 {
|
|
t.Error("Foreign key should have at least one column")
|
|
}
|
|
if fk.ReferencedTable == "" {
|
|
t.Error("Foreign key should have referenced table")
|
|
}
|
|
if len(fk.ReferencedColumns) == 0 {
|
|
t.Error("Foreign key should have at least one referenced column")
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if !hasFKs {
|
|
t.Error("Expected at least one foreign key relationship")
|
|
}
|
|
|
|
// Verify indexes exist on some tables
|
|
hasIndexes := false
|
|
for _, table := range schema.Tables {
|
|
if len(table.Indexes) > 0 {
|
|
hasIndexes = true
|
|
// Verify index properties
|
|
for _, idx := range table.Indexes {
|
|
if idx.Name == "" {
|
|
t.Error("Index should have a name")
|
|
}
|
|
if len(idx.Columns) == 0 {
|
|
t.Error("Index should have at least one column")
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if !hasIndexes {
|
|
t.Error("Expected at least one table with indexes")
|
|
}
|
|
}
|
|
|
|
func TestReader_ReadSchema(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
schema, err := reader.ReadSchema()
|
|
if err != nil {
|
|
t.Fatalf("ReadSchema() error = %v", err)
|
|
}
|
|
|
|
if schema == nil {
|
|
t.Fatal("ReadSchema() returned nil schema")
|
|
}
|
|
|
|
if schema.Name == "" {
|
|
t.Error("Expected non-empty schema name")
|
|
}
|
|
|
|
if len(schema.Tables) == 0 {
|
|
t.Fatal("Expected at least one table")
|
|
}
|
|
}
|
|
|
|
func TestReader_ReadTable(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
table, err := reader.ReadTable()
|
|
if err != nil {
|
|
t.Fatalf("ReadTable() error = %v", err)
|
|
}
|
|
|
|
if table == nil {
|
|
t.Fatal("ReadTable() returned nil table")
|
|
}
|
|
|
|
if table.Name == "" {
|
|
t.Error("Expected non-empty table name")
|
|
}
|
|
|
|
if table.Schema == "" {
|
|
t.Error("Expected non-empty schema name")
|
|
}
|
|
|
|
if len(table.Columns) == 0 {
|
|
t.Error("Expected at least one column")
|
|
}
|
|
|
|
// Verify column properties
|
|
for _, col := range table.Columns {
|
|
if col.Name == "" {
|
|
t.Error("Column should have a name")
|
|
}
|
|
if col.Type == "" {
|
|
t.Error("Column should have a type")
|
|
}
|
|
if col.Table != table.Name {
|
|
t.Errorf("Column table '%s' should match table name '%s'", col.Table, table.Name)
|
|
}
|
|
if col.Schema != table.Schema {
|
|
t.Errorf("Column schema '%s' should match table schema '%s'", col.Schema, table.Schema)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReader_ReadDatabase_InvalidPath(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: "/nonexistent/file.dctx",
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
_, err := reader.ReadDatabase()
|
|
if err == nil {
|
|
t.Error("Expected error for invalid file path")
|
|
}
|
|
}
|
|
|
|
func TestReader_ReadDatabase_EmptyPath(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: "",
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
_, err := reader.ReadDatabase()
|
|
if err == nil {
|
|
t.Error("Expected error for empty file path")
|
|
}
|
|
}
|
|
|
|
func TestReader_ReadSchema_EmptyPath(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: "",
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
_, err := reader.ReadSchema()
|
|
if err == nil {
|
|
t.Error("Expected error for empty file path")
|
|
}
|
|
}
|
|
|
|
func TestReader_ReadTable_EmptyPath(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: "",
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
_, err := reader.ReadTable()
|
|
if err == nil {
|
|
t.Error("Expected error for empty file path")
|
|
}
|
|
}
|
|
|
|
func TestGetPrimaryKey(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
db, err := reader.ReadDatabase()
|
|
if err != nil {
|
|
t.Fatalf("ReadDatabase() error = %v", err)
|
|
}
|
|
|
|
// Find a table with a primary key
|
|
var tableName string
|
|
var pk *models.Column
|
|
for _, schema := range db.Schemas {
|
|
for _, table := range schema.Tables {
|
|
pk = table.GetPrimaryKey()
|
|
if pk != nil {
|
|
tableName = table.Name
|
|
break
|
|
}
|
|
}
|
|
if pk != nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
if pk == nil {
|
|
t.Fatal("Expected to find at least one table with a primary key")
|
|
}
|
|
|
|
if pk.Name == "" {
|
|
t.Error("Primary key should have a name")
|
|
}
|
|
|
|
if !pk.IsPrimaryKey {
|
|
t.Error("Primary key column should have IsPrimaryKey set to true")
|
|
}
|
|
|
|
t.Logf("Found primary key '%s' in table '%s'", pk.Name, tableName)
|
|
}
|
|
|
|
func TestGetForeignKeys(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
db, err := reader.ReadDatabase()
|
|
if err != nil {
|
|
t.Fatalf("ReadDatabase() error = %v", err)
|
|
}
|
|
|
|
// Find a table with foreign keys
|
|
var tableName string
|
|
var fks []*models.Constraint
|
|
for _, schema := range db.Schemas {
|
|
for _, table := range schema.Tables {
|
|
fks = table.GetForeignKeys()
|
|
if len(fks) > 0 {
|
|
tableName = table.Name
|
|
break
|
|
}
|
|
}
|
|
if len(fks) > 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
if len(fks) == 0 {
|
|
t.Fatal("Expected to find at least one table with foreign keys")
|
|
}
|
|
|
|
t.Logf("Found %d foreign keys in table '%s'", len(fks), tableName)
|
|
|
|
// Verify foreign key structure
|
|
for i, fk := range fks {
|
|
if fk.Type != models.ForeignKeyConstraint {
|
|
t.Errorf("FK %d: Expected foreign key constraint type", i)
|
|
}
|
|
if fk.Name == "" {
|
|
t.Errorf("FK %d: Expected foreign key to have a name", i)
|
|
}
|
|
if len(fk.Columns) == 0 {
|
|
t.Errorf("FK %d: Expected foreign key to have at least one column", i)
|
|
}
|
|
if fk.ReferencedTable == "" {
|
|
t.Errorf("FK %d: Expected foreign key to have a referenced table", i)
|
|
}
|
|
if len(fk.ReferencedColumns) == 0 {
|
|
t.Errorf("FK %d: Expected foreign key to have at least one referenced column", i)
|
|
}
|
|
|
|
t.Logf("FK %d: %s.%s -> %s.%s",
|
|
i,
|
|
tableName,
|
|
fk.Columns,
|
|
fk.ReferencedTable,
|
|
fk.ReferencedColumns,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestDatabaseStructure(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
db, err := reader.ReadDatabase()
|
|
if err != nil {
|
|
t.Fatalf("ReadDatabase() error = %v", err)
|
|
}
|
|
|
|
// Comprehensive structure validation
|
|
for _, schema := range db.Schemas {
|
|
if schema.Name == "" {
|
|
t.Error("Schema should have a name")
|
|
}
|
|
|
|
for _, table := range schema.Tables {
|
|
if table.Name == "" {
|
|
t.Error("Table should have a name")
|
|
}
|
|
if table.Schema == "" {
|
|
t.Error("Table should have a schema")
|
|
}
|
|
|
|
// Verify columns
|
|
for _, col := range table.Columns {
|
|
if col.Name == "" {
|
|
t.Errorf("Column in table '%s' should have a name", table.Name)
|
|
}
|
|
if col.Type == "" {
|
|
t.Errorf("Column '%s' in table '%s' should have a type", col.Name, table.Name)
|
|
}
|
|
if col.Table != table.Name {
|
|
t.Errorf("Column '%s' table reference should match table name", col.Name)
|
|
}
|
|
if col.Schema != table.Schema {
|
|
t.Errorf("Column '%s' schema reference should match table schema", col.Name)
|
|
}
|
|
}
|
|
|
|
// Verify constraints
|
|
for _, constraint := range table.Constraints {
|
|
if constraint.Name == "" {
|
|
t.Errorf("Constraint in table '%s' should have a name", table.Name)
|
|
}
|
|
if constraint.Type == "" {
|
|
t.Errorf("Constraint '%s' should have a type", constraint.Name)
|
|
}
|
|
if constraint.Table != table.Name {
|
|
t.Errorf("Constraint '%s' table reference should match table name", constraint.Name)
|
|
}
|
|
}
|
|
|
|
// Verify indexes
|
|
for _, index := range table.Indexes {
|
|
if index.Name == "" {
|
|
t.Errorf("Index in table '%s' should have a name", table.Name)
|
|
}
|
|
if len(index.Columns) == 0 {
|
|
t.Errorf("Index '%s' should have at least one column", index.Name)
|
|
}
|
|
if index.Table != table.Name {
|
|
t.Errorf("Index '%s' table reference should match table name", index.Name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestColumnProperties(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
db, err := reader.ReadDatabase()
|
|
if err != nil {
|
|
t.Fatalf("ReadDatabase() error = %v", err)
|
|
}
|
|
|
|
// Find various column types
|
|
hasNotNullColumn := false
|
|
hasNullableColumn := false
|
|
hasDefaultValue := false
|
|
|
|
for _, schema := range db.Schemas {
|
|
for _, table := range schema.Tables {
|
|
for _, col := range table.Columns {
|
|
if col.NotNull {
|
|
hasNotNullColumn = true
|
|
} else {
|
|
hasNullableColumn = true
|
|
}
|
|
if col.Default != nil {
|
|
hasDefaultValue = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if !hasNotNullColumn {
|
|
t.Log("Note: No NOT NULL columns found (this may be valid for the test data)")
|
|
}
|
|
if !hasNullableColumn {
|
|
t.Log("Note: No nullable columns found (this may be valid for the test data)")
|
|
}
|
|
if !hasDefaultValue {
|
|
t.Log("Note: No columns with default values found (this may be valid for the test data)")
|
|
}
|
|
}
|
|
|
|
func TestRelationships(t *testing.T) {
|
|
opts := &readers.ReaderOptions{
|
|
FilePath: filepath.Join("..", "..", "..", "examples", "dctx", "example.dctx"),
|
|
}
|
|
|
|
reader := NewReader(opts)
|
|
db, err := reader.ReadDatabase()
|
|
if err != nil {
|
|
t.Fatalf("ReadDatabase() error = %v", err)
|
|
}
|
|
|
|
// Count total relationships across all tables
|
|
relationshipCount := 0
|
|
for _, schema := range db.Schemas {
|
|
for _, table := range schema.Tables {
|
|
relationshipCount += len(table.Relationships)
|
|
}
|
|
}
|
|
|
|
// The example.dctx file should have a significant number of relationships
|
|
// With the fix for nested field GUID mapping, we expect around 100+ relationships
|
|
if relationshipCount < 50 {
|
|
t.Errorf("Expected at least 50 relationships, got %d. This may indicate relationships are not being parsed correctly", relationshipCount)
|
|
}
|
|
|
|
t.Logf("Successfully parsed %d relationships", relationshipCount)
|
|
|
|
// Verify relationship properties
|
|
for _, schema := range db.Schemas {
|
|
for _, table := range schema.Tables {
|
|
for _, rel := range table.Relationships {
|
|
if rel.Name == "" {
|
|
t.Errorf("Relationship in table '%s' should have a name", table.Name)
|
|
}
|
|
if rel.FromTable == "" {
|
|
t.Errorf("Relationship '%s' should have a from table", rel.Name)
|
|
}
|
|
if rel.ToTable == "" {
|
|
t.Errorf("Relationship '%s' should have a to table", rel.Name)
|
|
}
|
|
if rel.ForeignKey == "" {
|
|
t.Errorf("Relationship '%s' should reference a foreign key", rel.Name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|