From: JINMEI Tatuya Date: Wed, 16 May 2012 07:38:32 +0000 (-0700) Subject: [1512] supported python hash for dns.Name and dns.RRClass. X-Git-Tag: trac2351_base~226^2~82^2~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=80c031beb751c45caed9faf239570e13c2aa5459;p=thirdparty%2Fkea.git [1512] supported python hash for dns.Name and dns.RRClass. a bit beyond of this specific task, but it will help the backend implementation much simpler. --- diff --git a/src/lib/dns/python/name_python.cc b/src/lib/dns/python/name_python.cc index ce556df74c..6758d0e966 100644 --- a/src/lib/dns/python/name_python.cc +++ b/src/lib/dns/python/name_python.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "pydnspp_common.h" #include "messagerenderer_python.h" @@ -114,6 +115,7 @@ PyObject* Name_reverse(s_Name* self); PyObject* Name_concatenate(s_Name* self, PyObject* args); PyObject* Name_downcase(s_Name* self); PyObject* Name_isWildCard(s_Name* self); +long Name_hash(PyObject* py_self); PyMethodDef Name_methods[] = { { "at", reinterpret_cast(Name_at), METH_VARARGS, @@ -518,6 +520,12 @@ Name_isWildCard(s_Name* self) { } } +long +Name_hash(PyObject* pyself) { + s_Name* const self = static_cast(pyself); + return (LabelSequence(*self->cppobj).getHash(false)); +} + } // end of unnamed namespace namespace isc { @@ -615,7 +623,7 @@ PyTypeObject name_type = { NULL, // tp_as_number NULL, // tp_as_sequence NULL, // tp_as_mapping - NULL, // tp_hash + Name_hash, // tp_hash NULL, // tp_call Name_str, // tp_str NULL, // tp_getattro diff --git a/src/lib/dns/python/rrclass_python.cc b/src/lib/dns/python/rrclass_python.cc index 00141872e9..2c3dae621c 100644 --- a/src/lib/dns/python/rrclass_python.cc +++ b/src/lib/dns/python/rrclass_python.cc @@ -52,6 +52,7 @@ PyObject* RRClass_str(PyObject* self); PyObject* RRClass_toWire(s_RRClass* self, PyObject* args); PyObject* RRClass_getCode(s_RRClass* self); PyObject* RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op); +long RRClass_hash(PyObject* pyself); // Static function for direct class creation PyObject* RRClass_IN(s_RRClass *self); @@ -264,6 +265,12 @@ PyObject* RRClass_ANY(s_RRClass*) { return (RRClass_createStatic(RRClass::ANY())); } +long +RRClass_hash(PyObject* pyself) { + s_RRClass* const self = static_cast(pyself); + return (self->cppobj->getCode()); +} + } // end anonymous namespace namespace isc { @@ -296,7 +303,7 @@ PyTypeObject rrclass_type = { NULL, // tp_as_number NULL, // tp_as_sequence NULL, // tp_as_mapping - NULL, // tp_hash + RRClass_hash, // tp_hash NULL, // tp_call RRClass_str, // tp_str NULL, // tp_getattro diff --git a/src/lib/dns/python/tests/name_python_test.py b/src/lib/dns/python/tests/name_python_test.py index 5263412af7..b3b6e6a14d 100644 --- a/src/lib/dns/python/tests/name_python_test.py +++ b/src/lib/dns/python/tests/name_python_test.py @@ -218,5 +218,16 @@ class NameTest(unittest.TestCase): self.assertTrue(self.name4 <= self.name1) self.assertFalse(self.name2 >= self.name1) + def test_hash(self): + # The same name should have the same hash value. + self.assertEqual(hash(Name('example.com')), hash(Name('example.com'))) + # Hash is case insensitive. + self.assertEqual(hash(Name('example.com')), hash(Name('EXAMPLE.COM'))) + # We cannot reliably test the case for different hash values, but + # we can at least confirm inequality is case insensitive. + if hash(Name('example.com')) != hash(Name('example.org')): + self.assertNotEqual(hash(Name('example.com')), + hash(Name('EXAMPLE.ORG'))) + if __name__ == '__main__': unittest.main() diff --git a/src/lib/dns/python/tests/rrclass_python_test.py b/src/lib/dns/python/tests/rrclass_python_test.py index 38d8c8c34d..a048c4c0f3 100644 --- a/src/lib/dns/python/tests/rrclass_python_test.py +++ b/src/lib/dns/python/tests/rrclass_python_test.py @@ -78,6 +78,14 @@ class RRClassTest(unittest.TestCase): self.assertTrue(self.c1 <= self.c2) self.assertFalse(self.c1 != other_rrclass) + def test_hash(self): + # Exploiting the knowledge that the hash value is the numeric class + # value, we can predict the comparison result. + self.assertEqual(hash(RRClass.IN()), hash(RRClass("IN"))) + self.assertEqual(hash(RRClass("in")), hash(RRClass("IN"))) + self.assertNotEqual(hash(RRClass.IN()), hash(RRClass.CH())) + self.assertNotEqual(hash(RRClass.IN()), hash(RRClass("CLASS65535"))) + def test_statics(self): self.assertEqual(RRClass.IN(), RRClass("IN")) self.assertEqual(RRClass.CH(), RRClass("CH"))