From 421cc6e870ff2a565339f46ec3c7491c8b0041de Mon Sep 17 00:00:00 2001 From: yukkop Date: Thu, 15 May 2025 18:54:56 +0000 Subject: [PATCH] test: `hemar`: +20 tests for parsing --- package/c/hemar/test/test_jsonb_path.sql | 4 +- package/c/hemar/test/test_template_parser.sql | 405 ++++++++++++++++++ 2 files changed, 407 insertions(+), 2 deletions(-) create mode 100755 package/c/hemar/test/test_template_parser.sql diff --git a/package/c/hemar/test/test_jsonb_path.sql b/package/c/hemar/test/test_jsonb_path.sql index 98c71e0..d247438 100755 --- a/package/c/hemar/test/test_jsonb_path.sql +++ b/package/c/hemar/test/test_jsonb_path.sql @@ -478,7 +478,7 @@ BEGIN RAISE WARNING 'Test %: Empty array/object edge cases (path="%"): % | PASSED: % (expected: empty array)', total_tests, current_path, result, passed; END IF; - + -- Print summary IF passed_tests = total_tests THEN RAISE NOTICE '------------------------------------'; @@ -497,4 +497,4 @@ BEGIN IF passed_tests != total_tests THEN RAISE EXCEPTION 'Tests failed: % of % tests did not pass', (total_tests - passed_tests), total_tests; END IF; -END $$; +END $$; diff --git a/package/c/hemar/test/test_template_parser.sql b/package/c/hemar/test/test_template_parser.sql new file mode 100755 index 0000000..8d83f44 --- /dev/null +++ b/package/c/hemar/test/test_template_parser.sql @@ -0,0 +1,405 @@ +-- Test file for hemar template parser +-- Run with: psql -f test_template_parser.sql + +-- Load extension if not already loaded +-- CREATE EXTENSION IF NOT EXISTS hemar; + +-- Create test function to validate template parsing +CREATE OR REPLACE FUNCTION test_template_parse(template_text text, expected_structure text) RETURNS boolean AS $$ +DECLARE + parsed_result text; + passed boolean; +BEGIN + BEGIN + parsed_result := hemar.parse(template_text); + passed := position(expected_structure in parsed_result) > 0; + EXCEPTION + WHEN OTHERS THEN + passed := false; + END; + + IF NOT passed THEN + RAISE WARNING 'Template parsing test failed!'; + RAISE WARNING 'Template: %', template_text; + RAISE WARNING 'Expected to find: %', expected_structure; + RAISE WARNING 'Actual result: %', parsed_result; + END IF; + + RETURN passed; +END; +$$ LANGUAGE plpgsql; + +-- Run the tests +DO $$ +DECLARE + total_tests integer := 0; + passed_tests integer := 0; + result boolean; +BEGIN + RAISE NOTICE 'Starting template parser tests...'; + + -- Test 1: Simple interpolation + total_tests := total_tests + 1; + result := test_template_parse( + '{{ simple_var }}', + 'INTERPOLATE: "simple_var"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Simple interpolation - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Simple interpolation - FAILED', total_tests; + END IF; + + -- Test 2: Interpolation with surrounding text + total_tests := total_tests + 1; + result := test_template_parse( + 'Hello, {{ name }}!', + 'TEXT: "Hello, " +INTERPOLATE: "name" +TEXT: "!"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Interpolation with surrounding text - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Interpolation with surrounding text - FAILED', total_tests; + END IF; + + -- Test 3: Simple section (for loop) + total_tests := total_tests + 1; + result := test_template_parse( + '{{ for item in items do }}{{ item }}{{ end }}', + 'SECTION: iterator="item", collection="items"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Simple section (for loop) - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Simple section (for loop) - FAILED', total_tests; + END IF; + + -- Test 4: Section with nested interpolation + total_tests := total_tests + 1; + result := test_template_parse( + '{{ for item in items do }}Name: {{ item.name }}{{ end }}', + 'SECTION: iterator="item", collection="items" + TEXT: "Name: " + INTERPOLATE: "item.name"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Section with nested interpolation - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Section with nested interpolation - FAILED', total_tests; + END IF; + + -- Test 5: Nested sections + total_tests := total_tests + 1; + result := test_template_parse( + '{{ for item in items do }}{{ for subitem in item.subitems do }}{{ subitem }}{{ end }}{{ end }}', + 'SECTION: iterator="item", collection="items" + SECTION: iterator="subitem", collection="item.subitems" + INTERPOLATE: "subitem"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Nested sections - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Nested sections - FAILED', total_tests; + END IF; + + -- Test 6: Include tag + total_tests := total_tests + 1; + result := test_template_parse( + '{{ include template_name }}', + 'INCLUDE: "template_name"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Include tag - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Include tag - FAILED', total_tests; + END IF; + + -- Test 7: Execute tag + total_tests := total_tests + 1; + result := test_template_parse( + '{{ exec RETURN my_function(arg1, arg2) }}', + 'EXECUTE: "RETURN my_function(arg1, arg2)"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Execute tag - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Execute tag - FAILED', total_tests; + END IF; + + -- Test 8: Complex mixed template + total_tests := total_tests + 1; + result := test_template_parse( + '
{{ for item in items do }}

{{ item.name }}

{{ include item.template }}{{ end }}
', + 'TEXT: "
" +SECTION: iterator="item", collection="items" + TEXT: "

" + INTERPOLATE: "item.name" + TEXT: "

" + INCLUDE: "item.template" +TEXT: "
"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Complex mixed template - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Complex mixed template - FAILED', total_tests; + END IF; + + -- Test 9: Execute tag with complex SQL + total_tests := total_tests + 1; + result := test_template_parse( + '{{ exec + IF condition THEN + RETURN ''value1''; + ELSE + RETURN ''value2''; + END IF; + }}', + 'EXECUTE: "IF condition THEN' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Execute tag with complex SQL - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Execute tag with complex SQL - FAILED', total_tests; + END IF; + + -- Test 10: Whitespace handling + total_tests := total_tests + 1; + result := test_template_parse( + '{{ spaced_var }}', + 'INTERPOLATE: "spaced_var"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Whitespace handling - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Whitespace handling - FAILED', total_tests; + END IF; + + -- Test 11: Multiple consecutive tags + total_tests := total_tests + 1; + result := test_template_parse( + '{{ var1 }}{{ var2 }}{{ var3 }}', + 'INTERPOLATE: "var1" +INTERPOLATE: "var2" +INTERPOLATE: "var3"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Multiple consecutive tags - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Multiple consecutive tags - FAILED', total_tests; + END IF; + + -- Test 12: Section with multiple nested elements + total_tests := total_tests + 1; + result := test_template_parse( + '{{ for item in items do }} +

{{ item.title }}

+

{{ item.description }}

+ {{ include item.footer }} + {{ end }}', + 'SECTION: iterator="item", collection="items" + TEXT: " +

" + INTERPOLATE: "item.title" + TEXT: "

+

" + INTERPOLATE: "item.description" + TEXT: "

+ " + INCLUDE: "item.footer" + TEXT: " + "' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Section with multiple nested elements - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Section with multiple nested elements - FAILED', total_tests; + END IF; + + -- Test 13: Empty template + total_tests := total_tests + 1; + result := test_template_parse( + '', + 'TEXT: ""' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Empty template - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Empty template - FAILED', total_tests; + END IF; + + -- Test 14: Just text, no tags + total_tests := total_tests + 1; + result := test_template_parse( + 'Just plain text, no tags here.', + 'TEXT: "Just plain text, no tags here."' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Just text, no tags - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Just text, no tags - FAILED', total_tests; + END IF; + + -- Test 15: Complex example from documentation + total_tests := total_tests + 1; + result := test_template_parse( + '
text before
+ + {{ include inner_template }} + + {{ name }} + + {{ for item in array do }} + some text: {{ name2 }} + {{ item.name }} + {{ end }} + +
code insertion:
+ {{ exec + context + ''{"name3": "zalupa"}''; + + IF context->condition THEN + RAISE INFO ''some log''; + + RETURN ''some text''; + END + RETURN ''some other text''; + }} + + ', + 'TEXT: "
text before
+ + " +INCLUDE: "inner_template" +TEXT: " + + " +INTERPOLATE: "name" +TEXT: " + + " +SECTION: iterator="item", collection="array"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Complex example from documentation - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Complex example from documentation - FAILED', total_tests; + END IF; + + -- Test 16: Multiple nested sections + total_tests := total_tests + 1; + result := test_template_parse( + '{{ for a in items do }} + {{ for b in a.items do }} + {{ for c in b.items do }} + {{ c.name }} + {{ end }} + {{ end }} + {{ end }}', + 'SECTION: iterator="a", collection="items" + TEXT: " + " + SECTION: iterator="b", collection="a.items" + TEXT: " + " + SECTION: iterator="c", collection="b.items" + TEXT: " + " + INTERPOLATE: "c.name" + TEXT: " + "' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Multiple nested sections - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Multiple nested sections - FAILED', total_tests; + END IF; + + -- Test 17: Interpolation with special characters + total_tests := total_tests + 1; + result := test_template_parse( + '{{ special@field }}', + 'INTERPOLATE: "special@field"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Interpolation with special characters - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Interpolation with special characters - FAILED', total_tests; + END IF; + + -- Test 18: Section with complex iterator and collection names + total_tests := total_tests + 1; + result := test_template_parse( + '{{ for complex_item.with.dots in complex_collection[0].items do }}{{ end }}', + 'SECTION: iterator="complex_item.with.dots", collection="complex_collection[0].items"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Section with complex iterator and collection names - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Section with complex iterator and collection names - FAILED', total_tests; + END IF; + + -- Test 19: Include with complex path + total_tests := total_tests + 1; + result := test_template_parse( + '{{ include templates[0].nested.path }}', + 'INCLUDE: "templates[0].nested.path"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Include with complex path - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Include with complex path - FAILED', total_tests; + END IF; + + -- Test 20: Execute with complex SQL and quotes + total_tests := total_tests + 1; + result := test_template_parse( + '{{ exec SELECT ''text with "double" quotes'' AS result; }}', + 'EXECUTE: "SELECT ''text with "double" quotes'' AS result;"' + ); + IF result THEN + passed_tests := passed_tests + 1; + RAISE NOTICE 'Test %: Execute with complex SQL and quotes - PASSED', total_tests; + ELSE + RAISE WARNING 'Test %: Execute with complex SQL and quotes - FAILED', total_tests; + END IF; + + -- Print summary + IF passed_tests = total_tests THEN + RAISE NOTICE '------------------------------------'; + RAISE NOTICE 'SUMMARY: % of % tests passed (100%%)', + passed_tests, total_tests; + RAISE NOTICE '------------------------------------'; + ELSE + RAISE WARNING '------------------------------------'; + RAISE WARNING 'SUMMARY: % of % tests passed (%)', + passed_tests, + total_tests, + round((passed_tests::numeric / total_tests::numeric) * 100, 2) || '%'; + RAISE WARNING '------------------------------------'; + END IF; + + IF passed_tests != total_tests THEN + RAISE EXCEPTION 'Tests failed: % of % tests did not pass', (total_tests - passed_tests), total_tests; + END IF; +END $$; \ No newline at end of file