Browse Source

[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.
JINMEI Tatuya 13 years ago
parent
commit
80c031beb7

+ 9 - 1
src/lib/dns/python/name_python.cc

@@ -20,6 +20,7 @@
 #include <dns/exceptions.h>
 #include <dns/messagerenderer.h>
 #include <dns/name.h>
+#include <dns/labelsequence.h>
 
 #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<PyCFunction>(Name_at), METH_VARARGS,
@@ -518,6 +520,12 @@ Name_isWildCard(s_Name* self) {
     }
 }
 
+long
+Name_hash(PyObject* pyself) {
+    s_Name* const self = static_cast<s_Name*>(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

+ 8 - 1
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<s_RRClass*>(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

+ 11 - 0
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()

+ 8 - 0
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"))