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) } } } } }