More Roundtrip tests
This commit is contained in:
@@ -1,110 +1,152 @@
|
||||
package dctx
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"encoding/xml"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/models"
|
||||
"git.warky.dev/wdevs/relspecgo/pkg/writers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestWriter_WriteDatabase_ReturnsError tests that WriteDatabase returns an error
|
||||
// since DCTX format is read-only
|
||||
func TestWriter_WriteDatabase_ReturnsError(t *testing.T) {
|
||||
db := models.InitDatabase("test_db")
|
||||
func TestWriter_WriteSchema(t *testing.T) {
|
||||
// 1. Create a sample schema
|
||||
schema := models.InitSchema("public")
|
||||
table := models.InitTable("users", "public")
|
||||
schema.Name = "TestDB"
|
||||
|
||||
// Table 1: users
|
||||
usersTable := models.InitTable("users", "public")
|
||||
usersTable.Comment = "Stores user information"
|
||||
idCol := models.InitColumn("id", "users", "public")
|
||||
idCol.Type = "bigint"
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
schema.Tables = append(schema.Tables, table)
|
||||
db.Schemas = append(db.Schemas, schema)
|
||||
|
||||
opts := &writers.WriterOptions{
|
||||
OutputPath: "/tmp/test.dctx",
|
||||
}
|
||||
|
||||
writer := NewWriter(opts)
|
||||
err := writer.WriteDatabase(db)
|
||||
|
||||
if err == nil {
|
||||
t.Error("WriteDatabase() should return an error for read-only format")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "read-only") {
|
||||
t.Errorf("Error message should mention 'read-only', got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriter_WriteSchema_ReturnsError tests that WriteSchema returns an error
|
||||
// since DCTX format is read-only
|
||||
func TestWriter_WriteSchema_ReturnsError(t *testing.T) {
|
||||
schema := models.InitSchema("public")
|
||||
table := models.InitTable("users", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "users", "public")
|
||||
idCol.Type = "bigint"
|
||||
table.Columns["id"] = idCol
|
||||
|
||||
schema.Tables = append(schema.Tables, table)
|
||||
|
||||
opts := &writers.WriterOptions{
|
||||
OutputPath: "/tmp/test.dctx",
|
||||
}
|
||||
|
||||
writer := NewWriter(opts)
|
||||
err := writer.WriteSchema(schema)
|
||||
|
||||
if err == nil {
|
||||
t.Error("WriteSchema() should return an error for read-only format")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "read-only") {
|
||||
t.Errorf("Error message should mention 'read-only', got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriter_WriteTable_ReturnsError tests that WriteTable returns an error
|
||||
// since DCTX format is read-only
|
||||
func TestWriter_WriteTable_ReturnsError(t *testing.T) {
|
||||
table := models.InitTable("users", "public")
|
||||
|
||||
idCol := models.InitColumn("id", "users", "public")
|
||||
idCol.Type = "bigint"
|
||||
idCol.Type = "serial"
|
||||
idCol.IsPrimaryKey = true
|
||||
table.Columns["id"] = idCol
|
||||
usersTable.Columns["id"] = idCol
|
||||
nameCol := models.InitColumn("name", "users", "public")
|
||||
nameCol.Type = "varchar"
|
||||
nameCol.Length = 100
|
||||
usersTable.Columns["name"] = nameCol
|
||||
pkIndex := models.InitIndex("users_pkey", "users", "public")
|
||||
pkIndex.Unique = true
|
||||
pkIndex.Columns = []string{"id"}
|
||||
usersTable.Indexes["users_pkey"] = pkIndex
|
||||
schema.Tables = append(schema.Tables, usersTable)
|
||||
|
||||
// Table 2: posts
|
||||
postsTable := models.InitTable("posts", "public")
|
||||
postsTable.Comment = "Stores blog posts"
|
||||
postIDCol := models.InitColumn("id", "posts", "public")
|
||||
postIDCol.Type = "serial"
|
||||
postIDCol.IsPrimaryKey = true
|
||||
postsTable.Columns["id"] = postIDCol
|
||||
titleCol := models.InitColumn("title", "posts", "public")
|
||||
titleCol.Type = "varchar"
|
||||
titleCol.Length = 255
|
||||
postsTable.Columns["title"] = titleCol
|
||||
userIDCol := models.InitColumn("user_id", "posts", "public")
|
||||
userIDCol.Type = "integer"
|
||||
postsTable.Columns["user_id"] = userIDCol
|
||||
postsPKIndex := models.InitIndex("posts_pkey", "posts", "public")
|
||||
postsPKIndex.Unique = true
|
||||
postsPKIndex.Columns = []string{"id"}
|
||||
postsTable.Indexes["posts_pkey"] = postsPKIndex
|
||||
|
||||
fkIndex := models.InitIndex("posts_user_id_idx", "posts", "public")
|
||||
fkIndex.Columns = []string{"user_id"}
|
||||
postsTable.Indexes["posts_user_id_idx"] = fkIndex
|
||||
schema.Tables = append(schema.Tables, postsTable)
|
||||
|
||||
// Constraint for the relationship
|
||||
fkConstraint := models.InitConstraint("fk_posts_users", models.ForeignKeyConstraint)
|
||||
fkConstraint.Table = "posts"
|
||||
fkConstraint.Schema = "public"
|
||||
fkConstraint.Columns = []string{"user_id"}
|
||||
fkConstraint.ReferencedTable = "users"
|
||||
fkConstraint.ReferencedSchema = "public"
|
||||
fkConstraint.ReferencedColumns = []string{"id"}
|
||||
postsTable.Constraints["fk_posts_users"] = fkConstraint
|
||||
|
||||
// Relation
|
||||
relation := models.InitRelation("fk_posts_users", "public")
|
||||
relation.FromTable = "posts"
|
||||
relation.ToTable = "users"
|
||||
relation.ForeignKey = "fk_posts_users"
|
||||
schema.Relations = append(schema.Relations, relation)
|
||||
|
||||
// 2. Setup writer
|
||||
outputPath := "/tmp/test.dctx"
|
||||
opts := &writers.WriterOptions{
|
||||
OutputPath: "/tmp/test.dctx",
|
||||
OutputPath: outputPath,
|
||||
}
|
||||
|
||||
writer := NewWriter(opts)
|
||||
err := writer.WriteTable(table)
|
||||
|
||||
if err == nil {
|
||||
t.Error("WriteTable() should return an error for read-only format")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "read-only") {
|
||||
t.Errorf("Error message should mention 'read-only', got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewWriter tests that NewWriter creates a valid writer instance
|
||||
func TestNewWriter(t *testing.T) {
|
||||
opts := &writers.WriterOptions{
|
||||
OutputPath: "/tmp/test.dctx",
|
||||
}
|
||||
|
||||
writer := NewWriter(opts)
|
||||
|
||||
if writer == nil {
|
||||
t.Error("NewWriter() should return a non-nil writer")
|
||||
}
|
||||
// 3. Write the schema
|
||||
err := writer.WriteSchema(schema)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if writer.options != opts {
|
||||
t.Error("Writer options should match the provided options")
|
||||
}
|
||||
}
|
||||
// 4. Read the file and unmarshal it
|
||||
actualBytes, err := os.ReadFile(outputPath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var dctx models.DCTXDictionary
|
||||
err = xml.Unmarshal(actualBytes, &dctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 5. Assert properties of the unmarshaled struct
|
||||
assert.Equal(t, "TestDB", dctx.Name)
|
||||
assert.Equal(t, "1", dctx.Version)
|
||||
assert.Len(t, dctx.Tables, 2)
|
||||
assert.Len(t, dctx.Relations, 1)
|
||||
|
||||
// Assert users table
|
||||
usersTableResult := dctx.Tables[0]
|
||||
assert.Equal(t, "users", usersTableResult.Name)
|
||||
assert.Len(t, usersTableResult.Fields, 2)
|
||||
assert.Len(t, usersTableResult.Keys, 1)
|
||||
userPK := usersTableResult.Keys[0]
|
||||
assert.True(t, userPK.Primary)
|
||||
assert.Equal(t, "users_pkey", userPK.Name)
|
||||
assert.Len(t, userPK.Components, 1)
|
||||
userPKComponent := userPK.Components[0]
|
||||
assert.NotEmpty(t, userPKComponent.FieldId)
|
||||
|
||||
// Assert posts table
|
||||
postsTableResult := dctx.Tables[1]
|
||||
assert.Equal(t, "posts", postsTableResult.Name)
|
||||
assert.Len(t, postsTableResult.Fields, 3)
|
||||
assert.Len(t, postsTableResult.Keys, 2)
|
||||
postsFK := postsTableResult.Keys[1] // Assuming order
|
||||
assert.False(t, postsFK.Primary)
|
||||
assert.Equal(t, "posts_user_id_idx", postsFK.Name)
|
||||
assert.Len(t, postsFK.Components, 1)
|
||||
postsFKComponent := postsFK.Components[0]
|
||||
assert.NotEmpty(t, postsFKComponent.FieldId)
|
||||
|
||||
// Assert relation
|
||||
relationResult := dctx.Relations[0]
|
||||
// PrimaryTable and ForeignTable should be GUIDs in DCTX format
|
||||
assert.NotEmpty(t, relationResult.PrimaryTable, "PrimaryTable should have a GUID")
|
||||
assert.NotEmpty(t, relationResult.ForeignTable, "ForeignTable should have a GUID")
|
||||
assert.NotEmpty(t, relationResult.PrimaryKey)
|
||||
assert.NotEmpty(t, relationResult.ForeignKey)
|
||||
|
||||
// Check if the table GUIDs match
|
||||
assert.Equal(t, usersTableResult.Guid, relationResult.PrimaryTable, "PrimaryTable GUID should match users table")
|
||||
assert.Equal(t, postsTableResult.Guid, relationResult.ForeignTable, "ForeignTable GUID should match posts table")
|
||||
|
||||
// Check if the key GUIDs match up
|
||||
assert.Equal(t, userPK.Guid, relationResult.PrimaryKey)
|
||||
assert.Equal(t, postsFK.Guid, relationResult.ForeignKey)
|
||||
|
||||
// Verify field mappings exist
|
||||
assert.NotEmpty(t, relationResult.ForeignMappings, "Relation should have ForeignMappings")
|
||||
assert.NotEmpty(t, relationResult.PrimaryMappings, "Relation should have PrimaryMappings")
|
||||
|
||||
// ForeignMapping should reference primary table (users) fields
|
||||
assert.Len(t, relationResult.ForeignMappings, 1)
|
||||
assert.NotEmpty(t, relationResult.ForeignMappings[0].Field)
|
||||
|
||||
// PrimaryMapping should reference foreign table (posts) fields
|
||||
assert.Len(t, relationResult.PrimaryMappings, 1)
|
||||
assert.NotEmpty(t, relationResult.PrimaryMappings[0].Field)
|
||||
}
|
||||
Reference in New Issue
Block a user