| import os | |
| from scripts.test import shared | |
| from . import utils | |
| class PoppyValidationTest(utils.BinaryenTestCase): | |
| def check_invalid(self, module, error): | |
| p = shared.run_process(shared.WASM_OPT + | |
| ['--experimental-poppy', '--print', '-o', os.devnull], | |
| input=module, check=False, capture_output=True) | |
| self.assertIn(error, p.stderr) | |
| self.assertIn('Fatal: error validating input', p.stderr) | |
| self.assertNotEqual(p.returncode, 0) | |
| def check_valid(self, module): | |
| p = shared.run_process(shared.WASM_OPT + | |
| ['--experimental-poppy', '--print', '-o', os.devnull], | |
| input=module, check=False, capture_output=True) | |
| self.assertEqual(p.stderr, "") | |
| self.assertEqual(p.returncode, 0) | |
| def test_top_level_pop(self): | |
| module = ''' | |
| (module | |
| (func $foo (result i32) | |
| (block (result i32) | |
| (i32.const 0) | |
| (pop i32) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "Unexpected top-level pop in block") | |
| def test_top_level_pop_fixed(self): | |
| module = ''' | |
| (module | |
| (func $foo (result i32) | |
| (block (result i32) | |
| (i32.const 0) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_valid(module) | |
| def test_incompatible_type(self): | |
| module = ''' | |
| (module | |
| (func $foo (result i32) | |
| (f32.const 42) | |
| (i32.const 42) | |
| (i32.add | |
| (pop i32) | |
| (pop i32) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "block element has incompatible type") | |
| self.check_invalid(module, "required: (i32 i32), available: (f32 i32)") | |
| def test_incorrect_pop_type(self): | |
| module = ''' | |
| (module | |
| (func $foo (result i32) | |
| (i32.const 42) | |
| (i32.const 42) | |
| (i32.add | |
| (pop i32) | |
| (pop f32) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "binary child types must be equal") | |
| def test_incompatible_type_fixed(self): | |
| module = ''' | |
| (module | |
| (func $foo (result i32) | |
| (i32.const 42) | |
| (i32.const 42) | |
| (i32.add | |
| (pop i32) | |
| (pop i32) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_valid(module) | |
| def test_incorrect_block_type(self): | |
| module = ''' | |
| (module | |
| (func $foo (result i32) | |
| (f32.const 42) | |
| (nop) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "block contents should satisfy block type") | |
| def test_nonblock_body(self): | |
| module = ''' | |
| (module | |
| (func $foo (result f32) | |
| (f32.const 42) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "Function body must be a block") | |
| def test_nonpop_if_condition(self): | |
| module = ''' | |
| (module | |
| (func $foo | |
| (nop) | |
| (i32.const 1) | |
| (if | |
| (i32.const 42) | |
| (block) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "Expected condition to be a Pop") | |
| def test_nonblock_if_true(self): | |
| module = ''' | |
| (module | |
| (func $foo | |
| (nop) | |
| (i32.const 1) | |
| (if | |
| (pop i32) | |
| (nop) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "Expected control flow child to be a block") | |
| def test_nonblock_if_false(self): | |
| module = ''' | |
| (module | |
| (func $foo | |
| (nop) | |
| (i32.const 1) | |
| (if | |
| (pop i32) | |
| (block) | |
| (nop) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "Expected control flow child to be a block") | |
| def test_nonblock_if_fixed(self): | |
| module = ''' | |
| (module | |
| (func $foo | |
| (nop) | |
| (i32.const 1) | |
| (if | |
| (pop i32) | |
| (block) | |
| (block) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_valid(module) | |
| def test_nonblock_loop_body(self): | |
| module = ''' | |
| (module | |
| (func $foo | |
| (nop) | |
| (loop | |
| (nop) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "Expected control flow child to be a block") | |
| def test_nonpop_child(self): | |
| module = ''' | |
| (module | |
| (func $foo (result i32) | |
| (i32.const 42) | |
| (i32.const 5) | |
| (i32.add | |
| (pop i32) | |
| (i32.const -1) | |
| ) | |
| ) | |
| ) | |
| ''' | |
| self.check_invalid(module, "Unexpected non-Pop child") |