Added project schema feature

This commit is contained in:
Martino Ferrari
2026-01-21 18:26:43 +01:00
parent 92dfa38294
commit 970b5697bd
16 changed files with 327 additions and 33 deletions

View File

@@ -30,7 +30,7 @@ func TestCheckCommand(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile(inputFile, config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
v.CheckUnused()
@@ -63,7 +63,7 @@ func TestCheckDuplicate(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile(inputFile, config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
foundError := false
@@ -95,7 +95,7 @@ func TestSignalNoClassValidation(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile(inputFile, config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
if len(v.Diagnostics) > 0 {

View File

@@ -31,7 +31,7 @@ func TestLSPDiagnostics(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile(inputFile, config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
// Check for expected diagnostics

View File

@@ -0,0 +1,83 @@
package integration
import (
"strings"
"testing"
"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 TestMDSWriterValidation(t *testing.T) {
// MDSWriter requires TreeName, NumberOfBuffers, etc.
content := `
+MyMDSWriter = {
Class = MDSWriter
NumberOfBuffers = 10
CPUMask = 1
StackSize = 1000000
// Missing TreeName
StoreOnTrigger = 0
EventName = "Update"
TimeRefresh = 1.0
+Signals = {}
}
`
p := parser.NewParser(content)
config, err := p.Parse()
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
idx := index.NewProjectTree()
idx.AddFile("mdswriter.marte", config)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false
for _, d := range v.Diagnostics {
if strings.Contains(d.Message, "Missing mandatory field 'TreeName'") {
found = true
break
}
}
if !found {
t.Error("Expected error for missing 'TreeName' in MDSWriter")
}
}
func TestMathExpressionGAMValidation(t *testing.T) {
// MathExpressionGAM requires Expression
content := `
+MyMath = {
Class = MathExpressionGAM
// Missing Expression
}
`
p := parser.NewParser(content)
config, err := p.Parse()
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
idx := index.NewProjectTree()
idx.AddFile("math.marte", config)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false
for _, d := range v.Diagnostics {
if strings.Contains(d.Message, "Missing mandatory field 'Expression'") {
found = true
break
}
}
if !found {
t.Error("Expected error for missing 'Expression' in MathExpressionGAM")
}
}

View File

@@ -28,7 +28,7 @@ func TestPIDGAMValidation(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("pid.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
foundKi := false
@@ -68,7 +68,7 @@ func TestFileDataSourceValidation(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("file.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false

View File

@@ -28,7 +28,7 @@ func TestRealTimeApplicationValidation(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("app.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
missingData := false
@@ -68,7 +68,7 @@ func TestGAMSchedulerValidation(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("scheduler.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false

View File

@@ -27,7 +27,7 @@ func TestSDNSubscriberValidation(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("sdn.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false
@@ -60,7 +60,7 @@ func TestFileWriterValidation(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("writer.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false

View File

@@ -37,7 +37,7 @@ func TestMultiFileNodeValidation(t *testing.T) {
// 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 := validator.NewValidator(idx, ".")
v.ValidateProject()
// +MyNode is split.
@@ -57,7 +57,7 @@ func TestMultiFileDuplicateField(t *testing.T) {
parseAndAddToIndex(t, idx, "integration/multifile_dup_1.marte")
parseAndAddToIndex(t, idx, "integration/multifile_dup_2.marte")
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
foundError := false
@@ -81,7 +81,7 @@ func TestMultiFileReference(t *testing.T) {
idx.ResolveReferences()
// Check if the reference in +SourceNode to TargetNode is resolved.
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
if len(v.Diagnostics) > 0 {
@@ -94,7 +94,7 @@ func TestHierarchicalPackageMerge(t *testing.T) {
parseAndAddToIndex(t, idx, "integration/hierarchical_pkg_1.marte")
parseAndAddToIndex(t, idx, "integration/hierarchical_pkg_2.marte")
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
// +MyObj should have Class (from file 1) and FieldX (from file 2).
@@ -135,7 +135,7 @@ func TestHierarchicalDuplicate(t *testing.T) {
parseAndAddToIndex(t, idx, "integration/hierarchical_dup_1.marte")
parseAndAddToIndex(t, idx, "integration/hierarchical_dup_2.marte")
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
foundError := false

View File

@@ -0,0 +1,71 @@
package integration
import (
"os"
"path/filepath"
"strings"
"testing"
"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 TestProjectSpecificSchema(t *testing.T) {
// Create temp dir
tmpDir, err := os.MkdirTemp("", "mdt_test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
// Define project schema
schemaContent := `
{
"classes": {
"ProjectClass": {
"fields": [
{"name": "CustomField", "type": "int", "mandatory": true}
]
}
}
}
`
err = os.WriteFile(filepath.Join(tmpDir, ".marte_schema.json"), []byte(schemaContent), 0644)
if err != nil {
t.Fatal(err)
}
// Define MARTe file using ProjectClass
marteContent := `
+Obj = {
Class = ProjectClass
// Missing CustomField
}
`
// We parse the content in memory, but we need the validator to look in tmpDir
p := parser.NewParser(marteContent)
config, err := p.Parse()
if err != nil {
t.Fatal(err)
}
idx := index.NewProjectTree()
idx.AddFile("project.marte", config)
// Pass tmpDir as projectRoot
v := validator.NewValidator(idx, tmpDir)
v.ValidateProject()
found := false
for _, d := range v.Diagnostics {
if strings.Contains(d.Message, "Missing mandatory field 'CustomField'") {
found = true
break
}
}
if !found {
t.Error("Expected error for missing 'CustomField' defined in project schema")
}
}

View File

@@ -26,7 +26,7 @@ func TestSchemaValidationMandatory(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("test.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false
@@ -60,7 +60,7 @@ func TestSchemaValidationType(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("test.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false
@@ -94,7 +94,7 @@ func TestSchemaValidationOrder(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("test.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
found := false
@@ -127,7 +127,7 @@ func TestSchemaValidationMandatoryNode(t *testing.T) {
idx := index.NewProjectTree()
idx.AddFile("test.marte", config)
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.ValidateProject()
for _, d := range v.Diagnostics {

View File

@@ -41,7 +41,7 @@ $App = {
idx.AddFile("test.marte", config)
idx.ResolveReferences()
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.CheckUnused()
foundUnused := false
@@ -85,7 +85,7 @@ $App = {
idx.AddFile("test.marte", config)
idx.ResolveReferences()
v := validator.NewValidator(idx)
v := validator.NewValidator(idx, ".")
v.CheckUnused()
foundUnusedSig2 := false