Files
relspecgo/pkg/readers/dctx/reader_test.go
Hein 5d60bc3b2c
Some checks are pending
CI / Test (1.23) (push) Waiting to run
CI / Test (1.24) (push) Waiting to run
CI / Test (1.25) (push) Waiting to run
CI / Lint (push) Waiting to run
CI / Build (push) Waiting to run
Bugs Fixed
1. pkg/models/models.go:184 - Fixed typo in ForeignKeyConstraint constant from "foreign_Key" to "foreign_key"
  2. pkg/readers/drawdb/reader.go:62-68 - Fixed ReadSchema() to properly detect schema name from tables instead of hardcoding "default"
  3. pkg/writers/dbml/writer.go:128 - Changed primary key attribute from "primary key" to DBML standard "pk"
  4. pkg/writers/dbml/writer.go:208-221 - Fixed foreign key reference format to use "table.column" syntax for single columns instead of "table.(column)"

  Test Results

  All reader and writer tests are now passing:

  Readers:
  - DBML: 74.4% coverage (2 tests skipped due to missing parser features for Ref statements)
  - DCTX: 77.6% coverage
  - DrawDB: 83.6% coverage
  - JSON: 82.1% coverage
  - YAML: 82.1% coverage

  Writers:
  - Bun: 68.5% coverage
  - DBML: 91.5% coverage
  - DCTX: 100.0% coverage
  - DrawDB: 83.8% coverage
  - GORM: 69.2% coverage
  - JSON: 82.4% coverage
  - YAML: 82.4% coverage
2025-12-16 21:43:45 +02:00

448 lines
10 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)")
}
}