"""Static-index correctness tests independent of the original payload corpus.""" import hashlib from pathlib import Path import tempfile import unittest import map_references as mapper class LexicalMappingTests(unittest.TestCase): def test_comments_and_literals_do_not_become_dependencies(self): source = '''// #include "fake1.ixpl" /* C::loadConfigFile("bad.cfg"); */ string x = "C::fake(1)"; string raw = \\"[\n#include "fake2.ixpl"\nC::fake(2);\n]"; #include "Core.ixpl" namespace C = Core; void real() { C::loadConfigFile("real.cfg", cfg); } ''' report = mapper.scan_ixpl(source) self.assertEqual([(x['include'],x['line']) for x in report['includes']], [('Core.ixpl',8)]) self.assertEqual([(c['qualifier'],c['method']) for c in report['qualified_calls']], [('Core','loadConfigFile')]) def test_balanced_call_arguments_and_opaque_commas(self): source = 'namespace C = Core;\nvoid f() { C::queueTask(id, int[]{1, 2}, nested(3, 4), "x,y"); }' call = mapper.scan_ixpl(source)['qualified_calls'][0] self.assertEqual(call['arguments'],['id','int[]{1, 2}','nested(3, 4)','"x,y"']) def test_interrupt_overloads_keep_signatures_and_source_lines(self): source = ('int INT_A = 7;\nvoid get(int &x);\n' 'void get(int &x) interrupt(+INT_A, x);\n' 'int get() {int x; interrupt(+INT_A, x); return x;}\n') wrappers = mapper.scan_ixpl(source)['interrupt_wrappers'] self.assertEqual([w['wrapper']['signature'] for w in wrappers],['void get(int &x)','int get()']) self.assertEqual([w['line'] for w in wrappers],[3,4]) self.assertEqual(mapper.constant_value(wrappers[0]['arguments'][0],{'INT_A':7}),7) def test_historical_struct_return_is_not_attached_to_previous_wrapper(self): source = ('type Brush = (int x);\nvoid deselect(int x) interrupt(+1,x);\n' 'Brush &read() {Brush b; interrupt(+2,b); return b;}\n') wrappers=mapper.scan_ixpl(source)['interrupt_wrappers'] self.assertEqual(wrappers[1]['wrapper']['name'],'read') self.assertEqual(wrappers[1]['wrapper']['line'],3) self.assertEqual(wrappers[1]['line'],3) def test_numeric_resolution_is_not_code_execution(self): self.assertEqual(mapper.constant_value('_INT_BEGIN + 5',{'_INT_BEGIN':249}),254) for value in ['__import__("os").system("bad")','X + 1','2 * 3']: with self.subTest(value=value), self.assertRaises(ValueError): mapper.constant_value(value,{}) def test_literal_names_resolve_only_unambiguous_bindings(self): report = mapper.scan_ixpl('string prefix = "camera.";\nstring name = prefix+"toggle";') self.assertEqual(mapper.literal_string('name',report['string_bindings']),'camera.toggle') for value in ['missing','"bad"+','call()']: self.assertIsNone(mapper.literal_string(value,report['string_bindings'])) self.assertIsNone(mapper.literal_string('prefix',{'prefix':[{'expression':'"a"'},{'expression':'"b"'}]})) self.assertIsNone(mapper.literal_string('cycle',{'cycle':[{'expression':'cycle'}]})) def test_large_multiline_literal_is_opaque(self): source = 'string data = \\"[' + (' ' * 1000 + '\n') * 80 + ']";\nvoid f() { Core::undo(); }' self.assertEqual(mapper.scan_ixpl(source)['qualified_calls'][0]['method'],'undo') for source in ['/* unterminated','string s = "bad','string s = \\"[bad']: with self.assertRaises(ValueError):mapper.lex(source) def test_build_graph_reports_missing_and_ambiguous_candidates(self): with tempfile.TemporaryDirectory() as temp: root = Path(temp).resolve() content = {'tools/includePaths.txt':b'..\\inc1\n..\\inc2\n', 'inc1/Core.ixpl':b'namespace Core {}', 'inc2/Core.ixpl':b'namespace Core {}', 'data/sources/plugins/tool.ixpl':b'#include "Core.ixpl"\n#include "Missing.ixpl"\n'} inventory = {'build':'synthetic','archive_sha256':'a'*64,'files':[]} for name,raw in content.items(): path=root/name;path.parent.mkdir(parents=True,exist_ok=True);path.write_bytes(raw) inventory['files'].append({'path':name,'sha256':hashlib.sha256(raw).hexdigest()}) build = mapper.index_build(root,inventory) plugin = next(f for f in build['files'] if f['category']=='plugin') self.assertEqual([e['status'] for e in plugin['includes']],['ambiguous','missing']) (root/'inc1/Core.ixpl').write_bytes(b'changed') with self.assertRaises(ValueError):mapper.index_build(root,inventory) def test_diffs_distinguish_renames_copies_and_changes(self): old={'build':'a','files':[{'path':'old.txt','sha256':'1'},{'path':'retained.txt','sha256':'2'}]} new={'build':'b','files':[{'path':'new.txt','sha256':'1'},{'path':'retained.txt','sha256':'2'}, {'path':'copy.txt','sha256':'2'}]} diff=mapper.differences([old,new])[0] self.assertEqual(diff['identical_rename_candidates'],[{'from':'old.txt','to':'new.txt'}]) self.assertEqual(diff['identical_copy_candidates'],[{'from':'retained.txt','to':'copy.txt'}])