201 lines
5.5 KiB
Go
201 lines
5.5 KiB
Go
package integration
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/marte-community/marte-dev-tools/internal/index"
|
|
"github.com/marte-community/marte-dev-tools/internal/parser"
|
|
"github.com/marte-community/marte-dev-tools/internal/validator"
|
|
)
|
|
|
|
func parseAndAddToIndex(t *testing.T, idx *index.ProjectTree, filePath string) {
|
|
content, err := ioutil.ReadFile(filePath)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read %s: %v", filePath, err)
|
|
}
|
|
|
|
p := parser.NewParser(string(content))
|
|
config, err := p.Parse()
|
|
if err != nil {
|
|
t.Fatalf("Parse failed for %s: %v", filePath, err)
|
|
}
|
|
|
|
idx.AddFile(filePath, config)
|
|
}
|
|
|
|
func TestMultiFileNodeValidation(t *testing.T) {
|
|
idx := index.NewProjectTree()
|
|
parseAndAddToIndex(t, idx, "integration/multifile_valid_1.marte")
|
|
parseAndAddToIndex(t, idx, "integration/multifile_valid_2.marte")
|
|
|
|
// Resolving references might be needed if the validator relies on it for merging implicitly
|
|
// But primarily we want to check if the validator sees the merged node.
|
|
// The current implementation of Validator likely iterates over the ProjectTree.
|
|
// If the ProjectTree doesn't merge nodes automatically, the Validator needs to do it.
|
|
// However, the spec says "The build tool, validator, and LSP must merge these definitions".
|
|
// Let's assume the Validator or Index does the merging logic.
|
|
|
|
v := validator.NewValidator(idx, ".")
|
|
v.ValidateProject()
|
|
|
|
// +MyNode is split.
|
|
// valid_1 has FieldA
|
|
// valid_2 has Class and FieldB
|
|
// If merging works, it should have a Class, so no error about missing Class.
|
|
|
|
for _, diag := range v.Diagnostics {
|
|
if strings.Contains(diag.Message, "must contain a 'Class' field") {
|
|
t.Errorf("Unexpected 'Class' field error for +MyNode: %s", diag.Message)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMultiFileDuplicateField(t *testing.T) {
|
|
idx := index.NewProjectTree()
|
|
parseAndAddToIndex(t, idx, "integration/multifile_dup_1.marte")
|
|
parseAndAddToIndex(t, idx, "integration/multifile_dup_2.marte")
|
|
|
|
v := validator.NewValidator(idx, ".")
|
|
v.ValidateProject()
|
|
|
|
foundError := false
|
|
for _, diag := range v.Diagnostics {
|
|
if strings.Contains(diag.Message, "Duplicate Field Definition") && strings.Contains(diag.Message, "FieldX") {
|
|
foundError = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !foundError {
|
|
t.Errorf("Expected duplicate field error for FieldX in +DupNode, but found none")
|
|
}
|
|
}
|
|
|
|
func TestMultiFileReference(t *testing.T) {
|
|
idx := index.NewProjectTree()
|
|
parseAndAddToIndex(t, idx, "integration/multifile_ref_1.marte")
|
|
parseAndAddToIndex(t, idx, "integration/multifile_ref_2.marte")
|
|
|
|
idx.ResolveReferences()
|
|
|
|
// Check if the reference in +SourceNode to TargetNode is resolved.
|
|
v := validator.NewValidator(idx, ".")
|
|
v.ValidateProject()
|
|
|
|
if len(v.Diagnostics) > 0 {
|
|
// Filter out irrelevant errors
|
|
}
|
|
}
|
|
|
|
func TestHierarchicalPackageMerge(t *testing.T) {
|
|
idx := index.NewProjectTree()
|
|
parseAndAddToIndex(t, idx, "integration/hierarchical_pkg_1.marte")
|
|
parseAndAddToIndex(t, idx, "integration/hierarchical_pkg_2.marte")
|
|
|
|
v := validator.NewValidator(idx, ".")
|
|
v.ValidateProject()
|
|
|
|
// +MyObj should have Class (from file 1) and FieldX (from file 2).
|
|
// If Class is missing, ValidateProject reports error.
|
|
|
|
for _, diag := range v.Diagnostics {
|
|
if strings.Contains(diag.Message, "must contain a 'Class' field") {
|
|
t.Errorf("Unexpected 'Class' field error for +MyObj: %s", diag.Message)
|
|
}
|
|
}
|
|
|
|
// We can also inspect the tree to verify FieldX is there (optional, but good for confidence)
|
|
projNode := idx.Root.Children["Proj"]
|
|
if projNode == nil {
|
|
t.Fatal("Proj node not found")
|
|
}
|
|
baseNode := projNode.Children["Base"]
|
|
if baseNode == nil {
|
|
t.Fatal("Base node not found")
|
|
}
|
|
objNode := baseNode.Children["MyObj"]
|
|
if objNode == nil {
|
|
t.Fatal("MyObj node not found in Base")
|
|
}
|
|
|
|
hasFieldX := false
|
|
for _, frag := range objNode.Fragments {
|
|
for _, def := range frag.Definitions {
|
|
if f, ok := def.(*parser.Field); ok && f.Name == "FieldX" {
|
|
hasFieldX = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !hasFieldX {
|
|
t.Error("FieldX not found in +MyObj")
|
|
}
|
|
}
|
|
|
|
func TestHierarchicalDuplicate(t *testing.T) {
|
|
idx := index.NewProjectTree()
|
|
parseAndAddToIndex(t, idx, "integration/hierarchical_dup_1.marte")
|
|
parseAndAddToIndex(t, idx, "integration/hierarchical_dup_2.marte")
|
|
|
|
v := validator.NewValidator(idx, ".")
|
|
v.ValidateProject()
|
|
|
|
foundError := false
|
|
for _, diag := range v.Diagnostics {
|
|
if strings.Contains(diag.Message, "Duplicate Field Definition") && strings.Contains(diag.Message, "FieldY") {
|
|
foundError = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !foundError {
|
|
t.Errorf("Expected duplicate field error for FieldY in +DupObj (hierarchical), but found none")
|
|
}
|
|
}
|
|
|
|
func TestIsolatedFileValidation(t *testing.T) {
|
|
idx := index.NewProjectTree()
|
|
|
|
// File 1: Has package. Defines SharedClass.
|
|
f1Content := `
|
|
#package Proj.Pkg
|
|
+SharedObj = { Class = SharedClass }
|
|
`
|
|
p1 := parser.NewParser(f1Content)
|
|
c1, _ := p1.Parse()
|
|
idx.AddFile("shared.marte", c1)
|
|
|
|
// File 2: No package. References SharedObj.
|
|
// Should NOT resolve to SharedObj in shared.marte because iso.marte is isolated.
|
|
f2Content := `
|
|
+IsoObj = {
|
|
Class = "MyClass"
|
|
Ref = SharedObj
|
|
}
|
|
`
|
|
p2 := parser.NewParser(f2Content)
|
|
c2, _ := p2.Parse()
|
|
idx.AddFile("iso.marte", c2)
|
|
|
|
idx.ResolveReferences()
|
|
|
|
// Find reference
|
|
var ref *index.Reference
|
|
for i := range idx.References {
|
|
if idx.References[i].File == "iso.marte" && idx.References[i].Name == "SharedObj" {
|
|
ref = &idx.References[i]
|
|
break
|
|
}
|
|
}
|
|
|
|
if ref == nil {
|
|
t.Fatal("Reference SharedObj not found in index")
|
|
}
|
|
|
|
if ref.Target != nil {
|
|
t.Errorf("Expected reference in isolated file to be unresolved, but got target in %s", ref.Target.Fragments[0].File)
|
|
}
|
|
}
|