Commit 2a98f3d1 authored by Jelte Jansen's avatar Jelte Jansen
Browse files

[2379] Add more tests and catches

And update doc and do a bit of style cleanup
parent ce492ecf
......@@ -20,6 +20,7 @@ datasrc_la_SOURCES += updater_python.cc updater_python.h
datasrc_la_SOURCES += journal_reader_python.cc journal_reader_python.h
datasrc_la_SOURCES += configurableclientlist_python.cc
datasrc_la_SOURCES += configurableclientlist_python.h
datasrc_la_SOURCES += zone_loader_python.cc zone_loader_python.h
datasrc_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
datasrc_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
......
......@@ -2,7 +2,7 @@ import sys
import os
# The datasource factory loader uses dlopen, as does python
# for its modules. Some dynamic linkers do not play nice if
# for its modules. Some dynamic linkers do not play nice if
# modules are not loaded with RTLD_GLOBAL, a symptom of which
# is that exceptions are not recognized by type. So to make
# sure this doesn't happen, we temporarily set RTLD_GLOBAL
......@@ -31,5 +31,4 @@ else:
sys.setdlopenflags(flags)
from isc.datasrc.sqlite3_ds import *
from isc.datasrc.master import *
......@@ -374,6 +374,16 @@ wrapDataSourceClient(DataSourceClient* client,
return (container.release());
}
DataSourceClient&
PyDataSourceClient_ToDataSourceClient(PyObject* client_obj) {
if (client_obj == NULL) {
isc_throw(PyCPPWrapperException,
"obj argument NULL in Name PyObject conversion");
}
const s_DataSourceClient* client = static_cast<const s_DataSourceClient*>(client_obj);
return (*client->client);
}
} // namespace python
} // namespace datasrc
} // namespace isc
......@@ -44,6 +44,9 @@ wrapDataSourceClient(DataSourceClient* client,
LifeKeeper>& life_keeper = boost::shared_ptr<ClientList::
FindResult::LifeKeeper>());
DataSourceClient&
PyDataSourceClient_ToDataSourceClient(PyObject* client_obj);
} // namespace python
} // namespace datasrc
} // namespace isc
......
......@@ -29,6 +29,7 @@
#include "updater_python.h"
#include "journal_reader_python.h"
#include "configurableclientlist_python.h"
#include "zone_loader_python.h"
#include <util/python/pycppwrapper_util.h>
#include <dns/python/pydnspp_common.h>
......@@ -180,6 +181,24 @@ initModulePart_ZoneIterator(PyObject* mod) {
return (true);
}
bool
initModulePart_ZoneLoader(PyObject* mod) {
// We initialize the static description object with PyType_Ready(),
// then add it to the module. This is not just a check! (leaving
// this out results in segmentation faults)
if (PyType_Ready(&zone_loader_type) < 0) {
return (false);
}
void* p = &zone_loader_type;
if (PyModule_AddObject(mod, "ZoneLoader",
static_cast<PyObject*>(p)) < 0) {
return (false);
}
Py_INCREF(&zone_loader_type);
return (true);
}
bool
initModulePart_ZoneUpdater(PyObject* mod) {
// We initialize the static description object with PyType_Ready(),
......@@ -234,8 +253,9 @@ initModulePart_ZoneJournalReader(PyObject* mod) {
}
PyObject* po_DataSourceError;
PyObject* po_OutOfZone;
PyObject* po_MasterFileError;
PyObject* po_NotImplemented;
PyObject* po_OutOfZone;
PyModuleDef iscDataSrc = {
{ PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
......@@ -260,6 +280,26 @@ PyInit_datasrc(void) {
return (NULL);
}
try {
po_DataSourceError = PyErr_NewException("isc.datasrc.Error", NULL,
NULL);
PyObjectContainer(po_DataSourceError).installToModule(mod, "Error");
po_MasterFileError = PyErr_NewException("isc.datasrc.MasterFileError",
po_DataSourceError, NULL);
PyObjectContainer(po_MasterFileError).installToModule(mod,
"MasterFileError");
po_OutOfZone = PyErr_NewException("isc.datasrc.OutOfZone", NULL, NULL);
PyObjectContainer(po_OutOfZone).installToModule(mod, "OutOfZone");
po_NotImplemented = PyErr_NewException("isc.datasrc.NotImplemented",
NULL, NULL);
PyObjectContainer(po_NotImplemented).installToModule(mod,
"NotImplemented");
} catch (...) {
Py_DECREF(mod);
return (NULL);
}
if (!initModulePart_DataSourceClient(mod)) {
Py_DECREF(mod);
return (NULL);
......@@ -290,17 +330,7 @@ PyInit_datasrc(void) {
return (NULL);
}
try {
po_DataSourceError = PyErr_NewException("isc.datasrc.Error", NULL,
NULL);
PyObjectContainer(po_DataSourceError).installToModule(mod, "Error");
po_OutOfZone = PyErr_NewException("isc.datasrc.OutOfZone", NULL, NULL);
PyObjectContainer(po_OutOfZone).installToModule(mod, "OutOfZone");
po_NotImplemented = PyErr_NewException("isc.datasrc.NotImplemented",
NULL, NULL);
PyObjectContainer(po_NotImplemented).installToModule(mod,
"NotImplemented");
} catch (...) {
if (!initModulePart_ZoneLoader(mod)) {
Py_DECREF(mod);
return (NULL);
}
......
......@@ -182,7 +182,7 @@ def records(input):
if paren == 1 or not record:
continue
ret = ' '.join(record)
record = []
oldsize = size
......
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
# old tests, TODO remove or change to use new API?
#PYTESTS = master_test.py
PYTESTS = datasrc_test.py sqlite3_ds_test.py clientlist_test.py
PYTESTS = datasrc_test.py sqlite3_ds_test.py
PYTESTS += clientlist_test.py zone_loader_test.py
EXTRA_DIST = $(PYTESTS)
EXTRA_DIST += testdata/brokendb.sqlite3
......
# Copyright (C) 2012 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import isc.datasrc
import isc.dns
import os
import unittest
TESTDATA_PATH = os.environ['TESTDATA_PATH'] + os.sep
TESTDATA_WRITE_PATH = os.environ['TESTDATA_WRITE_PATH'] + os.sep
READ_ZONE_DB_FILE = TESTDATA_PATH + "example.com.sqlite3"
WRITE_ZONE_DB_FILE = TESTDATA_WRITE_PATH + "rwtest.sqlite3.copied"
READ_ZONE_DB_CONFIG = "{ \"database_file\": \"" + READ_ZONE_DB_FILE + "\" }"
WRITE_ZONE_DB_CONFIG = "{ \"database_file\": \"" + WRITE_ZONE_DB_FILE + "\"}"
class ZoneLoaderTests(unittest.TestCase):
def setUp(self):
self.test_name = isc.dns.Name("example.com")
self.test_file = "foo.txt"
self.client = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
def test_bad_constructor(self):
self.assertRaises(TypeError, isc.datasrc.ZoneLoader)
self.assertRaises(TypeError, isc.datasrc.ZoneLoader, 1)
self.assertRaises(TypeError, isc.datasrc.ZoneLoader,
None, self.test_name, self.test_file)
self.assertRaises(TypeError, isc.datasrc.ZoneLoader,
self.client, None, self.test_file)
self.assertRaises(TypeError, isc.datasrc.ZoneLoader,
self.client, self.test_name, None)
self.assertRaises(TypeError, isc.datasrc.ZoneLoader,
self.client, self.test_name, self.test_file, 1)
def test_load_file(self):
#self.assertRaises(TypeError, isc.datasrc.ZoneLoader());
loader = isc.datasrc.ZoneLoader(self.client, self.test_name, self.test_file)
# This would currently loop
#loader.load()
def test_bad_file(self):
#self.assertRaises(TypeError, isc.datasrc.ZoneLoader());
loader = isc.datasrc.ZoneLoader(self.client, self.test_name, "no such file")
# This would currently loop
#loader.load()
def test_exception(self):
# Just check if masterfileerror is subclass of datasrc.Error
self.assertTrue(issubclass(isc.datasrc.MasterFileError,
isc.datasrc.Error))
if __name__ == "__main__":
isc.log.init("bind10")
isc.log.resetUnitTestRootLogger()
unittest.main()
namespace {
const char* const ZoneLoader_doc = "\
\n\
\n\
";
const char* const ZoneLoader_loadIncremental_doc = "\
\n\
\n\
";
const char* const ZoneLoader_load_doc = "\
\n\
\n\
";
} // unnamed namespace
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// Enable this if you use s# variants with PyArg_ParseTuple(), see
// http://docs.python.org/py3k/c-api/arg.html#strings-and-buffers
//#define PY_SSIZE_T_CLEAN
// Python.h needs to be placed at the head of the program file, see:
// http://docs.python.org/py3k/extending/extending.html#a-simple-example
#include <Python.h>
#include <util/python/pycppwrapper_util.h>
#include <datasrc/client.h>
#include <datasrc/database.h>
#include <datasrc/data_source.h>
#include <datasrc/sqlite3_accessor.h>
#include <datasrc/iterator.h>
#include <datasrc/zone.h>
#include <datasrc/zone_loader.h>
#include <dns/python/name_python.h>
//#include <dns/python/rrset_python.h>
//#include <dns/python/rrclass_python.h>
//#include <dns/python/rrtype_python.h>
#include <dns/python/pydnspp_common.h>
#include "client_python.h"
#include "datasrc.h"
#include "zone_loader_inc.cc"
using namespace std;
using namespace isc::util::python;
using namespace isc::dns::python;
using namespace isc::datasrc;
using namespace isc::datasrc::python;
namespace {
// The s_* Class simply covers one instantiation of the object
class s_ZoneLoader : public PyObject {
public:
s_ZoneLoader() : cppobj(NULL) {};
ZoneLoader* cppobj;
};
// Shortcut type which would be convenient for adding class variables safely.
typedef CPPPyObjectContainer<s_ZoneLoader, ZoneLoader> ZoneLoaderContainer;
// General creation and destruction
int
ZoneLoader_init(PyObject* po_self, PyObject* args, PyObject*) {
s_ZoneLoader* self = static_cast<s_ZoneLoader*>(po_self);
PyObject *po_ds_client;
PyObject *po_name;
char* master_file;
if (PyArg_ParseTuple(args, "O!O!s", &datasourceclient_type, &po_ds_client, &name_type, &po_name, &master_file)) {
try {
self->cppobj = new ZoneLoader(PyDataSourceClient_ToDataSourceClient(po_ds_client), PyName_ToName(po_name), master_file);
return (0);
} catch (const isc::datasrc::MasterFileError& mfe) {
PyErr_SetString(getDataSourceException("MasterFileError"), mfe.what());
} catch (const isc::datasrc::DataSourceError& dse) {
PyErr_SetString(getDataSourceException("Error"), dse.what());
} catch (const isc::NotImplemented& ni) {
PyErr_SetString(getDataSourceException("NotImplemented"), ni.what());
} catch (const std::exception& stde) {
PyErr_SetString(getDataSourceException("Error"), stde.what());
} catch (...) {
PyErr_SetString(getDataSourceException("Error"),
"Unexpected exception");
}
}
return (-1);
}
void
ZoneLoader_destroy(PyObject* po_self) {
s_ZoneLoader* self = static_cast<s_ZoneLoader*>(po_self);
delete self->cppobj;
self->cppobj = NULL;
Py_TYPE(self)->tp_free(self);
}
PyObject* ZoneLoader_load(PyObject* po_self, PyObject*) {
s_ZoneLoader* self = static_cast<s_ZoneLoader*>(po_self);
try {
self->cppobj->load();
Py_RETURN_NONE;
} catch (const isc::datasrc::MasterFileError& mfe) {
PyErr_SetString(getDataSourceException("MasterFileError"), mfe.what());
return (NULL);
} catch (const std::exception& exc) {
PyErr_SetString(getDataSourceException("Error"), exc.what());
return (NULL);
} catch (...) {
PyErr_SetString(getDataSourceException("Error"),
"Unexpected exception");
return (NULL);
}
}
// This list contains the actual set of functions we have in
// python. Each entry has
// 1. Python method name
// 2. Our static function here
// 3. Argument type
// 4. Documentation
PyMethodDef ZoneLoader_methods[] = {
/*
{ "get_origin", ZoneLoader_getOrigin, METH_NOARGS,
ZoneLoader_getOrigin_doc },
{ "get_class", ZoneLoader_getClass, METH_NOARGS, ZoneLoader_getClass_doc },
{ "find", ZoneLoader_find, METH_VARARGS, ZoneLoader_find_doc },
{ "find_all", ZoneLoader_find_all, METH_VARARGS, ZoneLoader_findAll_doc },
*/
{ "load", ZoneLoader_load, METH_NOARGS, ZoneLoader_load_doc },
{ NULL, NULL, 0, NULL }
};
} // end of unnamed namespace
namespace isc {
namespace datasrc {
namespace python {
PyTypeObject zone_loader_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"datasrc.ZoneLoader",
sizeof(s_ZoneLoader), // tp_basicsize
0, // tp_itemsize
ZoneLoader_destroy, // tp_dealloc
NULL, // tp_print
NULL, // tp_getattr
NULL, // tp_setattr
NULL, // tp_reserved
NULL, // tp_repr
NULL, // tp_as_number
NULL, // tp_as_sequence
NULL, // tp_as_mapping
NULL, // tp_hash
NULL, // tp_call
NULL, // tp_str
NULL, // tp_getattro
NULL, // tp_setattro
NULL, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
ZoneLoader_doc,
NULL, // tp_traverse
NULL, // tp_clear
NULL, // tp_richcompare
0, // tp_weaklistoffset
NULL, // tp_iter
NULL, // tp_iternext
ZoneLoader_methods, // tp_methods
NULL, // tp_members
NULL, // tp_getset
NULL, // tp_base
NULL, // tp_dict
NULL, // tp_descr_get
NULL, // tp_descr_set
0, // tp_dictoffset
ZoneLoader_init, // tp_init
NULL, // tp_alloc
PyType_GenericNew, // tp_new
NULL, // tp_free
NULL, // tp_is_gc
NULL, // tp_bases
NULL, // tp_mro
NULL, // tp_cache
NULL, // tp_subclasses
NULL, // tp_weaklist
NULL, // tp_del
0 // tp_version_tag
};
PyObject* po_MasterFileError;
} // namespace python
} // namespace datasrc
} // namespace isc
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef PYTHON_DATASRC_ZONE_LOADER_H
#define PYTHON_DATASRC_ZONE_LOADER_H 1
#include <Python.h>
namespace isc {
namespace datasrc {
namespace python {
extern PyTypeObject zone_loader_type;
} // namespace python
} // namespace datasrc
} // namespace isc
#endif // PYTHON_DATASRC_ZONE_LOADER_H
// Local Variables:
// mode: c++
// End:
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment