local test = dofile("test/test_harness.lua") package.path = package.path .. ";src/?.lua" local script_path = debug.getinfo(1, "S").source:gsub("^@", ""):match("(.*/)") or "." script_path = script_path:gsub("^test/", ""):gsub("/test$", "") if script_path == "" then script_path = "." end local diagnostics = dofile(script_path .. "/src/diagnostics.lua") local builtin = dofile(script_path .. "/src/builtin_instructions.lua") test.run_suite("Diagnostics Spec Tests", function() local function test_unknown_attribute_warning() local content = [[FUNCTION_BLOCK "Test" VAR_INPUT x { ExternalWriteable := 'False' } : Bool; END_VAR BEGIN END_FUNCTION_BLOCK ]] local diags = diagnostics.validate_diagnostics(content, {}, nil) local found = false for _, d in ipairs(diags) do if d.code == "SCL005" and d.message:find("ExternalWriteable") then found = true end end test.assert(found, "should warn on unknown attribute ExternalWriteable (typo)") end local function test_valid_attribute_no_warning() local content = [[FUNCTION_BLOCK "Test" VAR_INPUT x { ExternalWritable := 'False' } : Bool; END_VAR BEGIN END_FUNCTION_BLOCK ]] local diags = diagnostics.validate_diagnostics(content, {}, nil) local found = false for _, d in ipairs(diags) do if d.code == "SCL005" then found = true end end test.assert(not found, "should NOT warn on valid attribute ExternalWritable") end local function test_s7_setpoint_attribute() local content = [[TYPE "TestUDT" STRUCT x { S7_SetPoint := 'True' } : Byte; END_STRUCT; END_TYPE ]] local diags = diagnostics.validate_diagnostics(content, {}, nil) local found = false for _, d in ipairs(diags) do if d.code == "SCL005" then found = true end end test.assert(not found, "should NOT warn on S7_SetPoint attribute") end local function test_unknown_type_warning() local content = [[FUNCTION_BLOCK "Test" VAR x : NonExistentType; END_VAR BEGIN END_FUNCTION_BLOCK ]] local diags = diagnostics.validate_diagnostics(content, {}, nil) local found = false for _, d in ipairs(diags) do if d.code == "SCL003" and d.message:find("NonExistentType") then found = true end end test.assert(found, "should warn on unknown data type NonExistentType") end local function test_known_type_no_warning() local content = [[FUNCTION_BLOCK "Test" VAR x : VARIANT; y : LWORD; z : DTL; END_VAR BEGIN END_FUNCTION_BLOCK ]] local diags = diagnostics.validate_diagnostics(content, {}, nil) local found = false for _, d in ipairs(diags) do if d.code == "SCL003" then found = true end end test.assert(not found, "should NOT warn on known types VARIANT, LWORD, DTL") end local function test_iec_counter_no_warning() local content = [[FUNCTION_BLOCK "Test" VAR ctr : IEC_COUNTER; timer : IEC_TIMER; END_VAR BEGIN END_FUNCTION_BLOCK ]] local diags = diagnostics.validate_diagnostics(content, {}, nil) local found = false for _, d in ipairs(diags) do if d.code == "SCL003" then found = true end end test.assert(not found, "should NOT warn on IEC_COUNTER and IEC_TIMER") end test_unknown_attribute_warning() test_valid_attribute_no_warning() test_s7_setpoint_attribute() test_unknown_type_warning() test_known_type_no_warning() test_iec_counter_no_warning() end) test.report()