from chrysacase import ChrysalideTestCase from pychrysalide.analysis.scan import ScanExpression from pychrysalide.glibext import ComparableItem class TestScanExpression(ChrysalideTestCase): """TestCase for analysis.scan.ScanExpression.""" def testDirectInstances(self): """Reject direct instances.""" with self.assertRaisesRegex(RuntimeError, 'pychrysalide.analysis.scan.ScanExpression is an abstract class'): e = ScanExpression() def testBooleanComparison(self): """Compare custom scan expressions.""" class StrLenExpr(ScanExpression): def __init__(self, value): super().__init__(ScanExpression.ExprValueType.STRING) self._value = value def _cmp_rich(self, other, op): if op == ComparableItem.RichCmpOperation.EQ: return len(self._value) == len(other._value) e0 = StrLenExpr('00000000000') e1 = StrLenExpr('00000000000') e2 = StrLenExpr('000000000000000000000000000') self.assertTrue(e0 == e1) # !? # Python teste e0 != e1 (non implémenté), puis e1 != e0 (pareil) et en déduit une différence ! # self.assertFalse(e0 != e1) self.assertFalse(e0 == e2) # TypeError: '<' not supported between instances of 'StrLenExpr' and 'StrLenExpr' with self.assertRaisesRegex(TypeError, '\'<\' not supported between instances'): self.assertTrue(e0 < e1) # def testTypeSubclassing(self): # """Verify the data type subclassing is working.""" # class MyType(DataType): # def __init__(self, num): # super(MyType, self).__init__() # self._num = num # def _to_string(self, include): # return '%x' % self._num # def _dup(self): # return MyType(self._num) # tp = MyType(0x123) # self.assertEqual(str(tp), '123') # tp2 = tp.dup() # self.assertEqual(str(tp), str(tp2)) # def testTypeDefaultProperties(self): # """Check for default values of some type properties.""" # class MyPropType(DataType): # pass # tp = MyPropType() # self.assertTrue(tp.handle_namespaces) # self.assertFalse(tp.is_pointer) # self.assertFalse(tp.is_reference) # class MyPropType2(DataType): # def _handle_namespaces(self): # return True # def _is_pointer(self): # return 123 < 1234 # def _is_reference(self): # return False # tp2 = MyPropType2() # self.assertTrue(tp.handle_namespaces) # self.assertTrue(tp2.is_pointer) # self.assertFalse(tp2.is_reference) # def testTypeNamespaces(self): # """Test the type namespace property.""" # class MyNSType(DataType): # def __init__(self, name): # super(MyNSType, self).__init__() # self._name = name # def _to_string(self, include): # return self._name # tp = MyNSType('TP') # ns = MyNSType('NS') # self.assertIsNone(tp.namespace) # tp.namespace = (ns, '.') # self.assertEqual(str(tp), 'NS.TP') # self.assertEqual(tp.namespace, (ns, '.')) # def testTypeHash(self): # """Hash a user-defined type.""" # class MyUserType(DataType): # def __init__(self, name): # super(MyUserType, self).__init__() # self._name = name # def _hash(self): # return hash(self._name) # tp = MyUserType('random') # self.assertEqual(tp.hash, hash('random') & ((1 << 32) - 1)) # class MyOutOfRangeUserType(DataType): # hard_coded_hash = -8752470794866657507 # def __init__(self, name): # super(MyOutOfRangeUserType, self).__init__() # self._name = name # def _hash(self): # return self.hard_coded_hash # tp = MyOutOfRangeUserType('out-of-range') # self.assertEqual(tp.hash, MyOutOfRangeUserType.hard_coded_hash & ((1 << 32) - 1))