local test = dofile("test/test_harness.lua") package.path = package.path .. ";lua/?.lua" local udt_parser = require("tia.udt_parser") local db_parser = require("tia.db_parser") local fb_parser = require("tia.fb_parser") local function scan_directory(dir, ext) local files = {} local handle = io.popen('find "' .. dir .. '" -type f -name "*.' .. ext .. '" 2>/dev/null') if handle then for line in handle:lines() do if line ~= "" then table.insert(files, line) end end handle:close() end return files end local function test_parse_all_udt_files() udt_parser.clear_cache() local udt_files = scan_directory(test.REF_PROJECT .. "/PLC data types", "udt") test.assert_gt(#udt_files, 0, "should find UDT files in reference project") local parsed = 0 local failed = {} for _, filepath in ipairs(udt_files) do local file = io.open(filepath, "r") if file then local content = file:read("*all") file:close() local udt, err = udt_parser.parse_udt_content(content, filepath) if udt then parsed = parsed + 1 else table.insert(failed, filepath .. ": " .. (err or "unknown error")) end end end print(string.format("Parsed %d/%d UDT files", parsed, #udt_files)) if #failed > 0 then print("Failed files:") for _, f in ipairs(failed) do print(" " .. f) end end test.assert_gt(parsed, 0, "should parse at least one UDT file") end local function test_parse_all_db_files() db_parser.clear_cache() local db_files = scan_directory(test.REF_PROJECT .. "/Program blocks", "db") test.assert_gt(#db_files, 0, "should find DB files in reference project") local parsed = 0 local failed = {} for _, filepath in ipairs(db_files) do local file = io.open(filepath, "r") if file then local content = file:read("*all") file:close() local db, err = db_parser.parse_db_content(content, filepath) if db then parsed = parsed + 1 else table.insert(failed, filepath .. ": " .. (err or "unknown error")) end end end print(string.format("Parsed %d/%d DB files", parsed, #db_files)) if #failed > 0 then print("Failed files:") for _, f in ipairs(failed) do print(" " .. f) end end test.assert_gt(parsed, 0, "should parse at least one DB file") end local function test_parse_all_scl_files() fb_parser.clear_cache() local scl_files = scan_directory(test.REF_PROJECT .. "/Program blocks", "scl") test.assert_gt(#scl_files, 0, "should find SCL files in reference project") local parsed = 0 local failed = {} for _, filepath in ipairs(scl_files) do local file = io.open(filepath, "r") if file then local content = file:read("*all") file:close() local fb, err = fb_parser.parse_fb_content(content, filepath) if fb then parsed = parsed + 1 else table.insert(failed, filepath .. ": " .. (err or "unknown error")) end end end print(string.format("Parsed %d/%d SCL files", parsed, #scl_files)) if #failed > 0 then print("Failed files:") for _, f in ipairs(failed) do print(" " .. f) end end test.assert_gt(parsed, 0, "should parse at least one SCL file") end local function test_parse_xml_files() local xml_files = scan_directory(test.REF_PROJECT, "xml") local found = 0 for _, filepath in ipairs(xml_files) do local file = io.open(filepath, "r") if file then local content = file:read("*all") file:close() if content and #content > 10 then found = found + 1 end end end print(string.format("Found %d/%d XML files", found, #xml_files)) test.assert(found > 0, "should find XML files") end local function test_type_resolution() udt_parser.clear_cache() db_parser.clear_cache() fb_parser.clear_cache() local udt_content = [[ TYPE "inner_type" TITLE = Inner VERSION : 0.1 STRUCT x : Int; y : Bool; END_STRUCT; END_TYPE ]] local db_content = [[ DATA_BLOCK "test_db" TITLE = Test VERSION : 0.1 VAR myInner : "inner_type"; simple : Bool; END_VAR END_DATA_BLOCK ]] local fb_content = [[ FUNCTION_BLOCK "test_fb" TITLE = Test VERSION : 0.1 VAR_INPUT input1 : "inner_type"; END_VAR END_FUNCTION_BLOCK ]] local udt = udt_parser.parse_udt_content(udt_content, "inner.udt") if udt then udt_parser.register_inline_udt(udt) end local db = db_parser.parse_db_content(db_content, "test.db") if db then db_parser.register_inline_db(db) end local fb = fb_parser.parse_fb_content(fb_content, "test.scl") test.assert(udt_parser.is_udt_type("inner_type"), "inner_type should be recognized as UDT") test.assert(db_parser.is_db_type("test_db"), "test_db should be recognized as DB") local db_members = db_parser.get_db_members("test_db") if db_members and db_members[1] then test.assert_equals(db_members[1].is_udt, true, "DB member should be recognized as UDT reference") end end local function test_workspace_type_loading() plc_json.clear_cache() local types = plc_json.get_types(test.REF_PROJECT) local total_types = 0 for _ in pairs(types) do total_types = total_types + 1 end print(string.format("Loaded %d types from workspace", total_types)) test.assert_gt(total_types, 0, "should load types from reference project") end local function run_integration_tests() test.run_suite("Integration Tests - Reference Project", function() print("\n--- UDT Files ---") test_parse_all_udt_files() print("\n--- DB Files ---") test_parse_all_db_files() print("\n--- SCL Files ---") test_parse_all_scl_files() print("\n--- XML Files ---") test_parse_xml_files() print("\n--- Type Resolution ---") test_type_resolution() end) end if vim then vim.api.nvim_create_user_command("TestIntegration", function() run_integration_tests() end, {}) end run_integration_tests()