local test = dofile("test/test_harness.lua") package.path = package.path .. ";lua/?.lua" local db_parser = require("scl.db_parser") local function test_db_parser_basic() local content = [[ DATA_BLOCK "test_db" TITLE = Test DB VERSION : 0.1 //Test data block VAR member1 : Bool; member2 : Int; member3 : "other_udt"; END_VAR END_DATA_BLOCK ]] local db, err = db_parser.parse_db_content(content, "test.db") if db then db_parser.register_inline_db(db) end test.assert_not_nil(db, "parse_db_content should return db") test.assert_equals(db.name, "test_db", "DB name should be extracted") test.assert_equals(#db.members, 3, "should have 3 members") test.assert_equals(db.members[1].name, "member1", "first member name") test.assert_equals(db.members[3].is_udt, true, "third member is UDT type") end local function test_db_parser_attributes() local content = [[ DATA_BLOCK "attr_db" TITLE = Attr DB VERSION : 0.1 VAR attrMember{S7_SetPoint := 'True'}: Bool; normalMember : Int; END_VAR END_DATA_BLOCK ]] local db = db_parser.parse_db_content(content, "attr.db") test.assert_not_nil(db, "parse_db_content should return db") test.assert_equals(db.members[1].attributes.S7_SetPoint, "True", "attribute should be parsed") end local function test_db_parser_comments() local content = [[ DATA_BLOCK "comment_db" TITLE = Comment DB VERSION : 0.1 //This is a DB comment VAR member1 : Bool; //first member member2 : Int; //second member END_VAR END_DATA_BLOCK ]] local db = db_parser.parse_db_content(content, "comment.db") test.assert_not_nil(db, "parse_db_content should return db") test.assert_equals(db.comment, "This is a DB comment", "DB comment should be extracted") test.assert_equals(db.members[1].comment, "first member", "member comment should be extracted") end local function test_db_parser_array() local content = [[ DATA_BLOCK "array_db" TITLE = Array DB VERSION : 0.1 VAR arr : Array[0..9] of Int; arr2 : Array[0..5, 0..3] of Bool; END_VAR END_DATA_BLOCK ]] local db = db_parser.parse_db_content(content, "array.db") test.assert_not_nil(db, "parse_db_content should return db") test.assert(db.members[1].type:match("Array"), "array type should be preserved") end local function test_db_cache_operations() db_parser.clear_cache() test.assert_equals(db_parser.get_cache_count(), 0, "cache should be empty after clear") local content = [[ DATA_BLOCK "cached_db" TITLE = Cached DB VERSION : 0.1 VAR m1 : Bool; END_VAR END_DATA_BLOCK ]] local db = db_parser.parse_db_content(content, "cached.db") if db then db_parser.register_inline_db(db) end local cached = db_parser.get_db("cached_db") test.assert_not_nil(cached, "DB should be cached") test.assert_equals(db_parser.get_cache_count(), 1, "cache should have 1 entry") local names = db_parser.get_all_db_names() test.assert_equals(#names, 1, "should have 1 DB name") test.assert_equals(names[1], "cached_db", "DB name should match") end local function test_db_is_type() db_parser.clear_cache() local content = [[ DATA_BLOCK "known_db" TITLE = Known VERSION : 0.1 VAR m1 : Bool; END_VAR END_DATA_BLOCK ]] local db = db_parser.parse_db_content(content, "known.db") if db then db_parser.register_inline_db(db) end test.assert(db_parser.is_db_type("known_db"), "known_db should be recognized") test.assert(db_parser.is_db_type('"known_db"'), "quoted known_db should be recognized") test.assert(not db_parser.is_db_type("unknown_db"), "unknown_db should not be recognized") end local function test_db_members() db_parser.clear_cache() local content = [[ DATA_BLOCK "test_db" TITLE = Test VERSION : 0.1 VAR inner : "other_db"; simple : Bool; END_VAR END_DATA_BLOCK ]] local db = db_parser.parse_db_content(content, "test.db") if db then db_parser.register_inline_db(db) end local members = db_parser.get_db_members("test_db") test.assert_not_nil(members, "members should not be nil") if members and #members > 0 then test.assert_equals(members[1].name, "inner", "first member name") test.assert_equals(members[1].is_udt, true, "first member is UDT type") end end local function test_db_reference_files() db_parser.clear_cache() local ref_path = test.REF_PROJECT .. "/Program blocks/01_Machine/GlobalMachineData.db" local file = io.open(ref_path, "r") if not file then print("Warning: Reference DB file not found: " .. ref_path) return end local content = file:read("*all") file:close() local db = db_parser.parse_db_content(content, ref_path) if db then db_parser.register_inline_db(db) end test.assert_not_nil(db, "should parse reference DB file") test.assert_equals(db.name, "GlobalMachineData", "DB name should match") test.assert_gt(#db.members, 0, "should have members") local cached = db_parser.get_db("GlobalMachineData") test.assert_not_nil(cached, "DB should be cached") end local function test_db_multiple_reference_files() db_parser.clear_cache() local files = { test.REF_PROJECT .. "/Program blocks/01_Machine/GlobalMachineData.db", test.REF_PROJECT .. "/Program blocks/01_Machine/Equipments.db", test.REF_PROJECT .. "/Program blocks/10_Parameter/Parameter.db", } local parsed_count = 0 for _, filepath in ipairs(files) do local file = io.open(filepath, "r") if file then local content = file:read("*all") file:close() local db = db_parser.parse_db_content(content, filepath) if db then db_parser.register_inline_db(db) parsed_count = parsed_count + 1 end end end test.assert_gt(parsed_count, 0, "should parse at least one reference DB") test.assert_equals(db_parser.get_cache_count(), parsed_count, "cache should have correct count") end local function run_db_tests() test.run_suite("DB Parser Tests", function() print("\n--- Basic Tests ---") test_db_parser_basic() test_db_parser_attributes() test_db_parser_comments() test_db_parser_array() print("\n--- Cache Tests ---") test_db_cache_operations() test_db_is_type() test_db_members() print("\n--- Reference Project Tests ---") test_db_reference_files() test_db_multiple_reference_files() end) end if vim then vim.api.nvim_create_user_command("TestDb", function() run_db_tests() end, {}) end run_db_tests()