package integration import ( "bytes" "io/ioutil" "os" "strings" "testing" "github.com/marte-dev/marte-dev-tools/internal/builder" "github.com/marte-dev/marte-dev-tools/internal/formatter" "github.com/marte-dev/marte-dev-tools/internal/index" "github.com/marte-dev/marte-dev-tools/internal/parser" "github.com/marte-dev/marte-dev-tools/internal/validator" ) func TestCheckCommand(t *testing.T) { inputFile := "integration/error.marte" content, err := ioutil.ReadFile(inputFile) if err != nil { t.Fatalf("Failed to read %s: %v", inputFile, err) } p := parser.NewParser(string(content)) config, err := p.Parse() if err != nil { t.Fatalf("Parse failed: %v", err) } idx := index.NewProjectTree() idx.AddFile(inputFile, config) v := validator.NewValidator(idx) v.ValidateProject() v.CheckUnused() foundError := false for _, diag := range v.Diagnostics { if strings.Contains(diag.Message, "must contain a 'Class' field") { foundError = true break } } if !foundError { t.Errorf("Expected 'Class' field error in %s, but found none", inputFile) } } func TestCheckDuplicate(t *testing.T) { inputFile := "integration/check_dup.marte" content, err := ioutil.ReadFile(inputFile) if err != nil { t.Fatalf("Failed to read %s: %v", inputFile, err) } p := parser.NewParser(string(content)) config, err := p.Parse() if err != nil { t.Fatalf("Parse failed: %v", err) } idx := index.NewProjectTree() idx.AddFile(inputFile, config) v := validator.NewValidator(idx) v.ValidateProject() foundError := false for _, diag := range v.Diagnostics { if strings.Contains(diag.Message, "Duplicate Field Definition") { foundError = true break } } if !foundError { t.Errorf("Expected duplicate field error in %s, but found none", inputFile) } } func TestSignalNoClassValidation(t *testing.T) { inputFile := "integration/signal_no_class.marte" content, err := ioutil.ReadFile(inputFile) if err != nil { t.Fatalf("Failed to read %s: %v", inputFile, err) } p := parser.NewParser(string(content)) config, err := p.Parse() if err != nil { t.Fatalf("Parse failed: %v", err) } idx := index.NewProjectTree() idx.AddFile(inputFile, config) v := validator.NewValidator(idx) v.ValidateProject() if len(v.Diagnostics) > 0 { t.Errorf("Expected no errors for signal without Class, but got: %v", v.Diagnostics) } } func TestFmtCommand(t *testing.T) { inputFile := "integration/fmt.marte" content, err := ioutil.ReadFile(inputFile) if err != nil { t.Fatalf("Failed to read %s: %v", inputFile, err) } p := parser.NewParser(string(content)) config, err := p.Parse() if err != nil { t.Fatalf("Parse failed: %v", err) } var buf bytes.Buffer formatter.Format(config, &buf) output := buf.String() // Check for indentation if !strings.Contains(output, " Class = \"MyClass\"") { t.Error("Expected 2-space indentation for Class field") } // Check for sticky comments (no blank line between comment and field) if !strings.Contains(output, " // Sticky comment\n Field = 123") { t.Error("Expected sticky comment to be immediately followed by field") } if !strings.Contains(output, "Array = { 1 2 3 }") { t.Errorf("Expected formatted array '{ 1 2 3 }', got: %s", output) } // Check for inline comments inputFile2 := "integration/fmt_inline.marte" content2, err := ioutil.ReadFile(inputFile2) if err != nil { t.Fatalf("Failed to read %s: %v", inputFile2, err) } p2 := parser.NewParser(string(content2)) config2, err := p2.Parse() if err != nil { t.Fatalf("Parse failed: %v", err) } var buf2 bytes.Buffer formatter.Format(config2, &buf2) output2 := buf2.String() if !strings.Contains(output2, "+Node = { // Comment after open brace") { t.Error("Expected inline comment after open brace") } if !strings.Contains(output2, "Field1 = \"Value\" // Comment after value") { t.Error("Expected inline comment after field value") } } func TestBuildCommand(t *testing.T) { // Clean previous build os.RemoveAll("build_test") os.MkdirAll("build_test", 0755) defer os.RemoveAll("build_test") // Test Merge files := []string{"integration/build_merge_1.marte", "integration/build_merge_2.marte"} b := builder.NewBuilder(files) err := b.Build("build_test") if err != nil { t.Fatalf("Build failed: %v", err) } // Check output existence if _, err := os.Stat("build_test/TEST.marte"); os.IsNotExist(err) { t.Fatalf("Expected output file build_test/TEST.marte not found") } content, _ := ioutil.ReadFile("build_test/TEST.marte") output := string(content) if !strings.Contains(output, "FieldA = 1") || !strings.Contains(output, "FieldB = 2") { t.Error("Merged output missing fields") } // Test Order (Class First) filesOrder := []string{"integration/build_order_1.marte", "integration/build_order_2.marte"} bOrder := builder.NewBuilder(filesOrder) err = bOrder.Build("build_test") if err != nil { t.Fatalf("Build order test failed: %v", err) } contentOrder, _ := ioutil.ReadFile("build_test/TEST.marte") outputOrder := string(contentOrder) // Check for Class before Field classIdx := strings.Index(outputOrder, "Class = \"Ordered\"") fieldIdx := strings.Index(outputOrder, "Field = 1") if classIdx == -1 || fieldIdx == -1 { t.Fatal("Missing Class or Field in ordered output") } if classIdx > fieldIdx { t.Error("Expected Class to appear before Field in merged output") } }