Browse Source

[1455] implement rrset::toWire for empty rrsets

Needed for update messages
Jelte Jansen 13 years ago
parent
commit
9fee45c66f

+ 16 - 22
src/lib/dns/python/rrset_python.cc

@@ -251,28 +251,22 @@ RRset_toWire(PyObject* self_p, PyObject* args) {
     PyObject* mr;
     const s_RRset* self(static_cast<const s_RRset*>(self_p));
 
-    try {
-        if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
-            PyObject* bytes_o = bytes;
-
-            OutputBuffer buffer(4096);
-            self->cppobj->toWire(buffer);
-            PyObject* n = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
-            PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
-            // We need to release the object we temporarily created here
-            // to prevent memory leak
-            Py_DECREF(n);
-            return (result);
-        } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
-            self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
-            // If we return NULL it is seen as an error, so use this for
-            // None returns
-            Py_RETURN_NONE;
-        }
-    } catch (const EmptyRRset& ers) {
-        PyErr_Clear();
-        PyErr_SetString(po_EmptyRRset, ers.what());
-        return (NULL);
+    if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
+        PyObject* bytes_o = bytes;
+
+        OutputBuffer buffer(4096);
+        self->cppobj->toWire(buffer);
+        PyObject* n = PyBytes_FromStringAndSize(static_cast<const char*>(buffer.getData()), buffer.getLength());
+        PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
+        // We need to release the object we temporarily created here
+        // to prevent memory leak
+        Py_DECREF(n);
+        return (result);
+    } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, &mr)) {
+        self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
+        // If we return NULL it is seen as an error, so use this for
+        // None returns
+        Py_RETURN_NONE;
     }
     PyErr_Clear();
     PyErr_SetString(PyExc_TypeError,

+ 5 - 1
src/lib/dns/python/tests/rrset_python_test.py

@@ -96,7 +96,11 @@ class TestModuleSpec(unittest.TestCase):
         self.rrset_a.to_wire(buffer)
         self.assertEqual(exp_buffer, buffer)
 
-        self.assertRaises(EmptyRRset, self.rrset_a_empty.to_wire, buffer);
+        exp_buffer = bytearray(b'\x04test\x07example\x03com\x00\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x00')
+        buffer = bytearray()
+        self.rrset_a_empty.to_wire(buffer)
+        self.assertEqual(exp_buffer, buffer)
+
         self.assertRaises(TypeError, self.rrset_a.to_wire, 1)
 
     def test_to_wire_renderer(self):

+ 8 - 1
src/lib/dns/rrset.cc

@@ -65,7 +65,14 @@ rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit) {
     RdataIteratorPtr it = rrset.getRdataIterator();
 
     if (it->isLast()) {
-        isc_throw(EmptyRRset, "ToWire() is attempted for an empty RRset");
+        // For an empty RRset, write the name, type, class and TTL once,
+        // followed by empty rdata.
+        rrset.getName().toWire(output);
+        rrset.getType().toWire(output);
+        rrset.getClass().toWire(output);
+        rrset.getTTL().toWire(output);
+        output.writeUint16(0);
+        return (n);
     }
 
     // sort the set of Rdata based on rrset-order and sortlist, and possible

+ 13 - 4
src/lib/dns/tests/rrset_unittest.cc

@@ -197,6 +197,7 @@ TEST_F(RRsetTest, toText) {
     EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
 }
 
+#include <iostream>
 TEST_F(RRsetTest, toWireBuffer) {
     rrset_a.toWire(buffer);
 
@@ -206,7 +207,11 @@ TEST_F(RRsetTest, toWireBuffer) {
 
     // toWire() cannot be performed for an empty RRset.
     buffer.clear();
-    EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
+    rrset_a_empty.toWire(buffer);
+    wiredata.clear();
+    UnitTestUtil::readWireData("rrset_toWire3", wiredata);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
+                        buffer.getLength(), &wiredata[0], wiredata.size());
 }
 
 TEST_F(RRsetTest, toWireRenderer) {
@@ -219,9 +224,13 @@ TEST_F(RRsetTest, toWireRenderer) {
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
                         renderer.getLength(), &wiredata[0], wiredata.size());
 
-    // toWire() cannot be performed for an empty RRset.
-    renderer.clear();
-    EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
+    // toWire() can also be performed for an empty RRset.
+    buffer.clear();
+    rrset_a_empty.toWire(buffer);
+    wiredata.clear();
+    UnitTestUtil::readWireData("rrset_toWire3", wiredata);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
+                        buffer.getLength(), &wiredata[0], wiredata.size());
 }
 
 // test operator<<.  We simply confirm it appends the result of toText().

+ 12 - 0
src/lib/dns/tests/testdata/rrset_toWire3

@@ -0,0 +1,12 @@
+#
+# Rendering an empty IN/A RRset
+#
+#(4) t  e  s  t (7) e  x  a  m  p  l  e (3) c  o  m  .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# type/class: A = 1, IN = 1
+00 01 00 01
+# TTL: 3600
+00 00 0e 10
+#6  7
+# RDLENGTH: 0
+00 00