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")