diff options
Diffstat (limited to 'tests/arch')
-rw-r--r-- | tests/arch/immediate.py | 62 | ||||
-rw-r--r-- | tests/arch/instruction.py | 52 | ||||
-rw-r--r-- | tests/arch/operand.py | 72 | ||||
-rw-r--r-- | tests/arch/operands/immediate.py | 86 |
4 files changed, 210 insertions, 62 deletions
diff --git a/tests/arch/immediate.py b/tests/arch/immediate.py deleted file mode 100644 index 74b8069..0000000 --- a/tests/arch/immediate.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/python3-dbg -# -*- coding: utf-8 -*- - - -import pychrysalide -from chrysacase import ChrysalideTestCase -from pychrysalide import arch -from pychrysalide.arch import ImmOperand - - - -class TestImmediate(ChrysalideTestCase): - """TestCase for arch.ImmOperand.""" - - - def validateValue(self, value, size, padding, strings): - """Check all kinds of things with a given immediate operand.""" - - display = [ - ImmOperand.IOD_BIN, ImmOperand.IOD_OCT, - ImmOperand.IOD_DEC, - ImmOperand.IOD_HEX - ] - - for d in display: - - op = ImmOperand(size, value) - - self.assertTrue(op.size == size) - self.assertTrue(op.value == value) - - op.padding = padding - op.display = d - - string = op.to_string() - self.assertEqual(string, strings[d]) - - - def testByteOne(self): - """Run sanity checks on immediate operand with value 1.""" - - strings = { - ImmOperand.IOD_BIN: 'b1', - ImmOperand.IOD_OCT: '01', - ImmOperand.IOD_DEC: '1', - ImmOperand.IOD_HEX: '0x1' - } - - self.validateValue(1, arch.MDS_8_BITS_UNSIGNED, False, strings) - - - def testByteOnePadded(self): - """Run sanity checks on immediate operand with padded value 1.""" - - strings = { - ImmOperand.IOD_BIN: 'b00000001', - ImmOperand.IOD_OCT: '01', - ImmOperand.IOD_DEC: '1', - ImmOperand.IOD_HEX: '0x01' - } - - self.validateValue(1, arch.MDS_8_BITS_UNSIGNED, True, strings) diff --git a/tests/arch/instruction.py b/tests/arch/instruction.py new file mode 100644 index 0000000..da4d8c1 --- /dev/null +++ b/tests/arch/instruction.py @@ -0,0 +1,52 @@ + +import pychrysalide +from chrysacase import ChrysalideTestCase +from pychrysalide.arch import ArchInstruction + + +class TestProcessor(ChrysalideTestCase): + """TestCase for arch.ArchProcessor.""" + + + def testAbstractClass(self): + """Forbid instruction class instance.""" + + with self.assertRaisesRegex(RuntimeError, 'pychrysalide.arch.ArchInstruction is an abstract class'): + ins = ArchInstruction() + + + def testInstructionBasicImplementation(self): + """Implement basic custom instructions.""" + + + class TodoInstruction(ArchInstruction): + + def __init__(self): + super().__init__(0x123) + + + ins = TodoInstruction() + + with self.assertRaisesRegex(NotImplementedError, 'unexpected NULL value as encoding'): + print(ins.encoding) + + with self.assertRaisesRegex(NotImplementedError, 'unexpected NULL value as keyword'): + print(ins.keyword) + + + class CustomInstruction(ArchInstruction): + + def __init__(self): + super().__init__(0x123) + + def _get_encoding(self): + return 'custom' + + def _get_keyword(self): + return 'kw' + + + ins = CustomInstruction() + + self.assertEqual('custom', ins.encoding) + self.assertEqual('kw', ins.keyword) diff --git a/tests/arch/operand.py b/tests/arch/operand.py new file mode 100644 index 0000000..e8df8b5 --- /dev/null +++ b/tests/arch/operand.py @@ -0,0 +1,72 @@ + +import pychrysalide + +from chrysacase import ChrysalideTestCase +from pychrysalide.arch import ArchOperand +from pychrysalide.glibext import HashableObject, StringBuilder + + +class TestOperand(ChrysalideTestCase): + """TestCase for arch.ArchOperand.""" + + + def testAbstractClass(self): + """Forbid operand class instance.""" + + with self.assertRaisesRegex(RuntimeError, 'pychrysalide.arch.ArchOperand is an abstract class'): + pc = ArchOperand() + + + def testStringBuilderMethodsOverriding(self): + """Override the StringBuilder interface provided by native implementations.""" + + class MyOperand(ArchOperand, StringBuilder): + + def __init__(self): + super().__init__(self) + + def _to_string(self, flags=0): + return 'my-op' + + op = MyOperand() + + self.assertEqual(op.to_string(), 'my-op') + self.assertEqual(str(op), 'my-op') + self.assertEqual(f'{op}', 'my-op') + + + def testHashableObjectMethods(self): + """Test the HashableObject methods implemantation for operands.""" + + # Pas d'implementation de particulière de HashableObject, + # c'est donc la définition d'implémentation d'ArchOperand + # qui s'applique. + + # Spécificité de l'implémentation GLib : hash 32 bits + + class DefaultHashableOperand(ArchOperand): + pass + + def_op = DefaultHashableOperand() + + h = hash(def_op) + + self.assertEqual(0, h & ~0xffffffff) + + + # Définition particulière de l'opérande, sur la base de + # l'implémentation parente. + + class CustomHashableOperand(ArchOperand, HashableObject): + + def _hash(self): + h = self.parent_hash() + h &= ~0xffff + return h + + cust_op = CustomHashableOperand() + + h = hash(cust_op) + + self.assertEqual(0, h & 0xffff) + self.assertEqual(0, h & ~0xffffffff) diff --git a/tests/arch/operands/immediate.py b/tests/arch/operands/immediate.py new file mode 100644 index 0000000..c3fcb84 --- /dev/null +++ b/tests/arch/operands/immediate.py @@ -0,0 +1,86 @@ + +import pychrysalide + +from chrysacase import ChrysalideTestCase +from pychrysalide import MemoryDataSize +from pychrysalide.arch.operands import ImmediateOperand +from pychrysalide.glibext import StringBuilder + + +class TestImmediate(ChrysalideTestCase): + """TestCase for arch.ImmediateOperand.""" + + + def testBasicImmediate(self): + """Check basic properties of immediate values.""" + + imm = ImmediateOperand(MemoryDataSize._32_BITS_UNSIGNED, 0x123) + + self.assertEqual(imm.size, MemoryDataSize._32_BITS_UNSIGNED) + self.assertEqual(imm.value, 0x123) + self.assertFalse(imm.is_negative) + + + def testStringBuilderForImmediatesOverriding(self): + """Override the StringBuilder interface for immediate values.""" + + class MyImmOperand(ImmediateOperand, StringBuilder): + + def __init__(self): + super().__init__(MemoryDataSize._32_BITS_UNSIGNED, 0x123) + + def _to_string(self, flags=0): + return 'NaN' + + op = MyImmOperand() + + self.assertEqual(op.to_string(), 'NaN') + self.assertEqual(str(op), 'NaN') + self.assertEqual(f'{op}', 'NaN') + + + def validateValue(self, value, size, padding, strings): + """Check all kinds of things with a given immediate operand.""" + + for d in strings.keys(): + + op = ImmediateOperand(size, value) + + self.assertTrue(op.size == size) + self.assertTrue(op.value == value) + + if padding: + op.set_flag(ImmediateOperand.ImmOperandFlag.ZERO_PADDING) + else: + op.unset_flag(ImmediateOperand.ImmOperandFlag.ZERO_PADDING_BY_DEFAULT) + + op.display = d + + string = op.to_string() + self.assertEqual(string, strings[d]) + + + def testByteOne(self): + """Run sanity checks on immediate operand with value 1.""" + + strings = { + ImmediateOperand.ImmOperandDisplay.BIN: 'b1', + ImmediateOperand.ImmOperandDisplay.OCT: '01', + ImmediateOperand.ImmOperandDisplay.DEC: '1', + ImmediateOperand.ImmOperandDisplay.HEX: '0x1' + } + + self.validateValue(1, pychrysalide.MemoryDataSize._8_BITS_UNSIGNED, False, strings) + + + def testByteOnePadded(self): + """Run sanity checks on immediate operand with padded value 1.""" + + strings = { + ImmediateOperand.ImmOperandDisplay.BIN: 'b00000001', + ImmediateOperand.ImmOperandDisplay.OCT: '01', + ImmediateOperand.ImmOperandDisplay.DEC: '1', + ImmediateOperand.ImmOperandDisplay.HEX: '0x01' + } + + self.validateValue(1, pychrysalide.MemoryDataSize._8_BITS_UNSIGNED, True, strings) |