[svn] commit: r2364 - in /trunk: ./ src/bin/auth/ src/bin/auth/tests/ src/bin/xfrin/ src/lib/cc/ src/lib/config/ src/lib/config/tests/ src/lib/datasrc/ src/lib/datasrc/tests/ src/lib/dns/ src/lib/dns/rdata/generic/ src/lib/dns/tests/ src/lib/python/isc/cc/ src/lib/python/isc/cc/tests/
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Jun 30 19:05:31 UTC 2010
Author: jelte
Date: Wed Jun 30 19:05:31 2010
New Revision: 2364
Log:
Merge ticket 172 (JSON on cc channel)
This merge expands isc::data::Element with full JSON support, and removes the binary wire format. Python side uses built-in JSON module.
Added:
trunk/src/lib/python/isc/cc/tests/message_test.py
- copied unchanged from r2362, branches/trac172/src/lib/python/isc/cc/tests/message_test.py
Removed:
trunk/src/lib/python/isc/cc/tests/test.py
Modified:
trunk/ (props changed)
trunk/src/bin/auth/auth_srv.cc
trunk/src/bin/auth/tests/auth_srv_unittest.cc
trunk/src/bin/xfrin/ (props changed)
trunk/src/lib/cc/ (props changed)
trunk/src/lib/cc/data.cc
trunk/src/lib/cc/data.h
trunk/src/lib/cc/data_unittests.cc
trunk/src/lib/cc/session.cc
trunk/src/lib/config/ccsession.cc
trunk/src/lib/config/config_data.cc
trunk/src/lib/config/config_data.h
trunk/src/lib/config/module_spec.cc
trunk/src/lib/config/module_spec.h
trunk/src/lib/config/tests/ccsession_unittests.cc
trunk/src/lib/config/tests/config_data_unittests.cc
trunk/src/lib/config/tests/fake_session.cc
trunk/src/lib/config/tests/module_spec_unittests.cc
trunk/src/lib/datasrc/ (props changed)
trunk/src/lib/datasrc/tests/datasrc_unittest.cc
trunk/src/lib/datasrc/tests/sqlite3_unittest.cc
trunk/src/lib/dns/ (props changed)
trunk/src/lib/dns/rdata/generic/rrsig_46.cc (props changed)
trunk/src/lib/dns/tests/ (props changed)
trunk/src/lib/python/isc/cc/message.py
trunk/src/lib/python/isc/cc/tests/Makefile.am
trunk/src/lib/python/isc/cc/tests/session_test.py
Modified: trunk/src/bin/auth/auth_srv.cc
==============================================================================
--- trunk/src/bin/auth/auth_srv.cc (original)
+++ trunk/src/bin/auth/auth_srv.cc Wed Jun 30 19:05:31 2010
@@ -274,7 +274,7 @@
bool is_default;
string item("database_file");
ElementPtr value = cs_->getValue(is_default, item);
- final = Element::createFromString("{}");
+ final = Element::createMap();
// If the value is the default, and we are running from
// a specific directory ('from build'), we need to use
Modified: trunk/src/bin/auth/tests/auth_srv_unittest.cc
==============================================================================
--- trunk/src/bin/auth/tests/auth_srv_unittest.cc (original)
+++ trunk/src/bin/auth/tests/auth_srv_unittest.cc Wed Jun 30 19:05:31 2010
@@ -236,7 +236,7 @@
const bool expect_success)
{
const ElementPtr config_answer =
- server->updateConfig(Element::createFromString(dbfile));
+ server->updateConfig(Element::fromJSON(dbfile));
EXPECT_EQ(Element::map, config_answer->getType());
EXPECT_TRUE(config_answer->contains("result"));
Modified: trunk/src/lib/cc/data.cc
==============================================================================
--- trunk/src/lib/cc/data.cc (original)
+++ trunk/src/lib/cc/data.cc Wed Jun 30 19:05:31 2010
@@ -26,29 +26,34 @@
#include <boost/algorithm/string.hpp> // for iequals
+#include <cmath>
+
using namespace std;
-
-namespace {
-const unsigned char PROTOCOL_VERSION[4] = { 0x53, 0x6b, 0x61, 0x6e };
-
-const unsigned char ITEM_BLOB = 0x01;
-const unsigned char ITEM_HASH = 0x02;
-const unsigned char ITEM_LIST = 0x03;
-const unsigned char ITEM_NULL = 0x04;
-const unsigned char ITEM_BOOL = 0x05;
-const unsigned char ITEM_INT = 0x06;
-const unsigned char ITEM_REAL = 0x07;
-const unsigned char ITEM_UTF8 = 0x08;
-const unsigned char ITEM_MASK = 0x0f;
-
-const unsigned char ITEM_LENGTH_32 = 0x00;
-const unsigned char ITEM_LENGTH_16 = 0x10;
-const unsigned char ITEM_LENGTH_8 = 0x20;
-const unsigned char ITEM_LENGTH_MASK = 0x30;
-}
namespace isc {
namespace data {
+
+std::string
+Element::str()
+{
+ std::stringstream ss;
+ toJSON(ss);
+ return ss.str();
+}
+
+std::string
+Element::toWire()
+{
+ std::stringstream ss;
+ toJSON(ss);
+ return ss.str();
+}
+
+void
+Element::toWire(std::ostream& ss)
+{
+ toJSON(ss);
+}
//
// The following methods are effectively empty, and their parameters are
@@ -58,7 +63,7 @@
// installed files we define the methods here.
//
bool
-Element::getValue(int& t UNUSED_PARAM) {
+Element::getValue(long int& t UNUSED_PARAM) {
return false;
}
@@ -88,7 +93,7 @@
}
bool
-Element::setValue(const int v UNUSED_PARAM) {
+Element::setValue(const long int v UNUSED_PARAM) {
return false;
}
@@ -179,15 +184,11 @@
namespace {
inline void
-throwParseError(const std::string& error, const std::string& file, int line = 0, int pos = 0)
-{
- if (line != 0 || pos != 0) {
- std::stringstream ss;
- ss << error << " in " + file + ":" << line << ":" << pos;
- throw ParseError(ss.str());
- } else {
- throw ParseError(error);
- }
+throwJSONError(const std::string& error, const std::string& file, int line, int pos)
+{
+ std::stringstream ss;
+ ss << error << " in " + file + ":" << line << ":" << pos;
+ isc_throw(JSONError, ss.str());
}
}
@@ -203,7 +204,12 @@
// factory functions
//
ElementPtr
-Element::create(const int i) {
+Element::create() {
+ return ElementPtr(new NullElement());
+}
+
+ElementPtr
+Element::create(const long int i) {
return ElementPtr(new IntElement(i));
}
@@ -223,24 +229,18 @@
}
ElementPtr
-Element::create(const std::vector<ElementPtr>& v) {
- return ElementPtr(new ListElement(v));
-}
-
-ElementPtr
-Element::create(const std::map<std::string, ElementPtr>& m) {
- for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
- it != m.end(); ++it) {
- if ((*it).first.length() > 255) {
- isc_throw(TypeError, "Map tag is too long");
- }
- }
- return ElementPtr(new MapElement(m));
+Element::createList() {
+ return ElementPtr(new ListElement());
+}
+
+ElementPtr
+Element::createMap() {
+ return ElementPtr(new MapElement());
}
//
-// helper functions for createFromString factory
+// helper functions for fromJSON factory
//
namespace {
bool
@@ -300,15 +300,17 @@
--pos;
return;
} else {
- throwParseError(std::string("'") + c + "' read, one of \"" + chars + "\" expected", file, line, pos);
- }
- }
- throwParseError(std::string("EOF read, one of \"") + chars + "\" expected", file, line, pos);
-}
-
+ throwJSONError(std::string("'") + c + "' read, one of \"" + chars + "\" expected", file, line, pos);
+ }
+ }
+ throwJSONError(std::string("EOF read, one of \"") + chars + "\" expected", file, line, pos);
+}
+
+// TODO: Should we check for all other official escapes here (and
+// error on the rest)?
std::string
str_from_stringstream(std::istream &in, const std::string& file, const int line,
- int& pos) throw (ParseError)
+ int& pos) throw (JSONError)
{
char c = 0;
std::stringstream ss;
@@ -318,7 +320,7 @@
c = in.get();
++pos;
} else {
- throwParseError("String expected", file, line, pos);
+ throwJSONError("String expected", file, line, pos);
}
while (c != EOF && c != '"') {
ss << c;
@@ -342,36 +344,47 @@
return ss.str();
}
-inline int
-count_chars_i(int i) {
- int result = 1;
- while (i > 10) {
- ++result;
- i = i / 10;
- }
- return result;
-}
-
-inline int
-count_chars_d(double d) {
- int result = 1;
- while (d < 1.0) {
- ++result;
- d = d * 10;
- }
- return result;
-}
-
-ElementPtr
-from_stringstream_int_or_double(std::istream &in, int &pos) {
- int i;
- in >> i;
- pos += count_chars_i(i);
- if (in.peek() == '.') {
- double d;
- in >> d;
- pos += count_chars_d(i);
- d += i;
+static std::string
+number_from_stringstream(std::istream &in, int& pos) {
+ std::stringstream ss;
+ while (isdigit(in.peek()) || in.peek() == '+' || in.peek() == '-' ||
+ in.peek() == '.' || in.peek() == 'e' || in.peek() == 'E') {
+ ss << (char) in.get();
+ }
+ pos += ss.str().size();
+ return ss.str();
+}
+
+// Should we change from IntElement and DoubleElement to NumberElement
+// that can also hold an e value? (and have specific getters if the
+// value is larger than an int can handle)
+ElementPtr
+from_stringstream_number(std::istream &in, int &pos) {
+ long int i = 0;
+ double d = 0.0;
+ bool is_double = false;
+ char *endptr;
+
+ std::string number = number_from_stringstream(in, pos);
+
+ i = strtol(number.c_str(), &endptr, 10);
+ if (*endptr != '\0') {
+ d = strtod(number.c_str(), &endptr);
+ is_double = true;
+ if (*endptr != '\0') {
+ isc_throw(JSONError, std::string("Bad number: ") + number);
+ } else {
+ if (d == HUGE_VAL || d == -HUGE_VAL) {
+ isc_throw(JSONError, std::string("Number overflow: ") + number);
+ }
+ }
+ } else {
+ if (i == LONG_MAX || i == LONG_MIN) {
+ isc_throw(JSONError, std::string("Number overflow: ") + number);
+ }
+ }
+
+ if (is_double) {
return Element::create(d);
} else {
return Element::create(i);
@@ -388,13 +401,26 @@
} else if (boost::iequals(word, "False")) {
return Element::create(false);
} else {
- throwParseError(std::string("Bad boolean value: ") + word, file, line, pos);
- // above is a throw shortcur, return empty is never reached
+ throwJSONError(std::string("Bad boolean value: ") + word, file, line, pos);
+ // above is a throw shortcurt, return empty is never reached
return ElementPtr();
}
}
ElementPtr
+from_stringstream_null(std::istream &in, const std::string& file,
+ const int line, int& pos)
+{
+ const std::string word = word_from_stringstream(in, pos);
+ if (boost::iequals(word, "null")) {
+ return Element::create();
+ } else {
+ throwJSONError(std::string("Bad null value: ") + word, file, line, pos);
+ return ElementPtr();
+ }
+}
+
+ElementPtr
from_stringstream_string(std::istream& in, const std::string& file, int& line, int& pos)
{
return Element::create(str_from_stringstream(in, file, line, pos));
@@ -404,27 +430,27 @@
from_stringstream_list(std::istream &in, const std::string& file, int& line, int& pos)
{
char c = 0;
- std::vector<ElementPtr> v;
+ ElementPtr list = Element::createList();
ElementPtr cur_list_element;
skip_chars(in, " \t\n", line, pos);
while (c != EOF && c != ']') {
if (in.peek() != ']') {
- cur_list_element = Element::createFromString(in, file, line, pos);
- v.push_back(cur_list_element);
+ cur_list_element = Element::fromJSON(in, file, line, pos);
+ list->add(cur_list_element);
skip_to(in, file, line, pos, ",]", " \t\n");
}
c = in.get();
pos++;
}
- return Element::create(v);
+ return list;
}
ElementPtr
from_stringstream_map(std::istream &in, const std::string& file, int& line,
int& pos)
{
- std::map<std::string, ElementPtr> m;
+ ElementPtr map = Element::createMap();
skip_chars(in, " \t\n", line, pos);
char c = in.peek();
if (c == '}') {
@@ -432,45 +458,88 @@
c = in.get();
} else {
while (c != EOF && c != '}') {
- std::pair<std::string, ElementPtr> p;
-
- p.first = str_from_stringstream(in, file, line, pos);
- if (p.first.length() > 255) {
- // Map tag has one-byte length field in wire format, so the
- // length cannot exceed 255.
- throwParseError("Map tag is too long", file, line, pos);
- }
+ std::string key = str_from_stringstream(in, file, line, pos);
skip_to(in, file, line, pos, ":", " \t\n");
// skip the :
in.get();
pos++;
- p.second = Element::createFromString(in, file, line, pos);
- m.insert(p);
+
+ ElementPtr value = Element::fromJSON(in, file, line, pos);
+ map->set(key, value);
+
skip_to(in, file, line, pos, ",}", " \t\n");
c = in.get();
pos++;
}
}
- return Element::create(m);
-}
-}
-
-ElementPtr
-Element::createFromString(std::istream& in) throw(ParseError) {
+ return map;
+}
+}
+
+std::string
+Element::typeToName(Element::types type)
+{
+ switch(type) {
+ case Element::integer:
+ return std::string("integer");
+ case Element::real:
+ return std::string("real");
+ case Element::boolean:
+ return std::string("boolean");
+ case Element::string:
+ return std::string("string");
+ case Element::list:
+ return std::string("list");
+ case Element::map:
+ return std::string("map");
+ case Element::null:
+ return std::string("null");
+ case Element::any:
+ return std::string("any");
+ default:
+ return std::string("unknown");
+ }
+}
+
+Element::types
+Element::nameToType(const std::string& type_name) {
+ if (type_name == "integer") {
+ return Element::integer;
+ } else if (type_name == "real") {
+ return Element::real;
+ } else if (type_name == "boolean") {
+ return Element::boolean;
+ } else if (type_name == "string") {
+ return Element::string;
+ } else if (type_name == "list") {
+ return Element::list;
+ } else if (type_name == "map") {
+ return Element::map;
+ } else if (type_name == "null") {
+ return Element::null;
+ } else if (type_name == "any") {
+ return Element::any;
+ } else {
+ isc_throw(TypeError, type_name + " is not a valid type name");
+ }
+}
+
+ElementPtr
+Element::fromJSON(std::istream& in) throw(JSONError) {
int line = 1, pos = 1;
- return createFromString(in, "<istream>", line, pos);
-}
-
-ElementPtr
-Element::createFromString(std::istream& in, const std::string& file_name) throw(ParseError)
+ return fromJSON(in, "<istream>", line, pos);
+}
+
+ElementPtr
+Element::fromJSON(std::istream& in, const std::string& file_name) throw(JSONError)
{
int line = 1, pos = 1;
- return createFromString(in, file_name, line, pos);
-}
-
-ElementPtr
-Element::createFromString(std::istream &in, const std::string& file, int& line, int& pos) throw(ParseError)
+ return fromJSON(in, file_name, line, pos);
+}
+
+ElementPtr
+Element::fromJSON(std::istream &in, const std::string& file, int& line, int& pos) throw(JSONError)
{
char c = 0;
ElementPtr element;
@@ -490,8 +559,11 @@
case '8':
case '9':
case '0':
+ case '-':
+ case '+':
+ case '.':
in.putback(c);
- element = from_stringstream_int_or_double(in, pos);
+ element = from_stringstream_number(in, pos);
el_read = true;
break;
case 't':
@@ -500,6 +572,12 @@
case 'F':
in.putback(c);
element = from_stringstream_bool(in, file, line, pos);
+ el_read = true;
+ break;
+ case 'n':
+ case 'N':
+ in.putback(c);
+ element = from_stringstream_null(in, file, line, pos);
el_read = true;
break;
case '"':
@@ -518,62 +596,65 @@
case EOF:
break;
default:
- throwParseError(std::string("error: unexpected character ") + c, file, line, pos);
+ throwJSONError(std::string("error: unexpected character ") + c, file, line, pos);
break;
}
}
if (el_read) {
return element;
} else {
- throw ParseError("nothing read");
- }
-}
-
-ElementPtr
-Element::createFromString(const std::string &in) {
+ isc_throw(JSONError, "nothing read");
+ }
+}
+
+ElementPtr
+Element::fromJSON(const std::string &in) {
std::stringstream ss;
ss << in;
- return createFromString(ss, "<string>");
-}
-
-//
-// a general to_str() function
-//
-std::string
-IntElement::str() {
- std::stringstream ss;
+ return fromJSON(ss, "<string>");
+}
+
+// to JSON format
+
+void
+IntElement::toJSON(std::ostream& ss)
+{
ss << intValue();
- return ss.str();
-}
-
-std::string
-DoubleElement::str() {
- std::stringstream ss;
+}
+
+void
+DoubleElement::toJSON(std::ostream& ss)
+{
ss << doubleValue();
- return ss.str();
-}
-
-std::string
-BoolElement::str() {
- if (b) {
- return "True";
- } else {
- return "False";
- }
-}
-
-std::string
-StringElement::str() {
- std::stringstream ss;
+}
+
+void
+BoolElement::toJSON(std::ostream& ss)
+{
+ if (boolValue()) {
+ ss << "true";
+ } else {
+ ss << "false";
+ }
+}
+
+void
+NullElement::toJSON(std::ostream& ss)
+{
+ ss << "null";
+}
+
+void
+StringElement::toJSON(std::ostream& ss)
+{
ss << "\"";
ss << stringValue();
ss << "\"";
- return ss.str();
-}
-
-std::string
-ListElement::str() {
- std::stringstream ss;
+}
+
+void
+ListElement::toJSON(std::ostream& ss)
+{
ss << "[ ";
const std::vector<ElementPtr>& v = listValue();
@@ -582,16 +663,15 @@
if (it != v.begin()) {
ss << ", ";
}
- ss << (*it)->str();
+ (*it)->toJSON(ss);
}
ss << " ]";
- return ss.str();
-}
-
-std::string
-MapElement::str() {
- std::stringstream ss;
- ss << "{";
+}
+
+void
+MapElement::toJSON(std::ostream& ss)
+{
+ ss << "{ ";
const std::map<std::string, ElementPtr>& m = mapValue();
for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
@@ -601,13 +681,12 @@
}
ss << "\"" << (*it).first << "\": ";
if ((*it).second) {
- ss << (*it).second->str();
+ (*it).second->toJSON(ss);
} else {
ss << "None";
}
}
- ss << "}";
- return ss.str();
+ ss << " }";
}
// throws when one of the types in the path (except the one
@@ -634,169 +713,12 @@
}
}
-//
-// Decode from wire format.
-//
-namespace {
-ElementPtr decode_element(std::stringstream& in, int& in_length);
-
-unsigned char
-get_byte(std::stringstream& in) {
- const int c = in.get();
- if (c == EOF) {
- throw DecodeError("End of data while decoding wire format message");
- }
-
- return c;
-}
-
-std::string
-decode_tag(std::stringstream& in, int& item_length) {
- char buf[256];
-
- const int len = get_byte(in);
- item_length--;
-
- in.read(buf, len);
- if (in.fail()) {
- throw DecodeError();
- }
- buf[len] = 0;
- item_length -= len;
-
- return std::string(buf, len);
-}
-
-ElementPtr
-decode_bool(std::stringstream& in) {
- const char c = in.get();
-
- if (c == '1') {
- return Element::create(true);
- } else {
- return Element::create(false);
- }
-}
-
-ElementPtr
-decode_int(std::stringstream& in) {
- int me;
- return from_stringstream_int_or_double(in, me);
-}
-
-ElementPtr
-decode_real(std::stringstream& in) {
- int me;
- return from_stringstream_int_or_double(in, me);
-}
-
-ElementPtr
-decode_blob(std::stringstream& in, const int item_length) {
- vector<char> buf(item_length + 1);
-
- in.read(&buf[0], item_length);
- if (in.fail()) {
- throw DecodeError();
- }
- buf[item_length] = 0;
-
- return Element::create(std::string(&buf[0], item_length));
-}
-
-ElementPtr
-decode_hash(std::stringstream& in, int item_length) {
- std::map<std::string, ElementPtr> m;
- std::pair<std::string, ElementPtr> p;
-
- while (item_length > 0) {
- p.first = decode_tag(in, item_length);
- p.second = decode_element(in, item_length);
- m.insert(p);
- }
-
- return Element::create(m);
-}
-
-ElementPtr
-decode_list(std::stringstream& in, int item_length) {
- std::vector<ElementPtr> v;
-
- while (item_length > 0) {
- v.push_back(decode_element(in, item_length));
- }
- return Element::create(v);
-}
-
-ElementPtr
-decode_null() {
- return Element::create("NULL");
-}
-
-ElementPtr
-decode_element(std::stringstream& in, int& in_length) {
- ElementPtr element;
-
- const unsigned char type_and_length = get_byte(in);
- const unsigned char type = type_and_length & ITEM_MASK;
- const unsigned char lenbytes = type_and_length & ITEM_LENGTH_MASK;
- in_length--;
-
- int item_length = 0;
- switch (lenbytes) {
- case ITEM_LENGTH_32:
- item_length |= get_byte(in);
- item_length <<= 8;
- item_length |= get_byte(in);
- item_length <<= 8;
- in_length -= 2; // only 2 here, we will get more later
- case ITEM_LENGTH_16:
- item_length |= get_byte(in);
- item_length <<= 8;
- in_length--; // only 1 here
- case ITEM_LENGTH_8:
- item_length |= get_byte(in);
- in_length--;
- }
-
- in_length -= item_length;
-
- switch (type) {
- case ITEM_BOOL:
- element = decode_bool(in);
- break;
- case ITEM_INT:
- element = decode_int(in);
- break;
- case ITEM_REAL:
- element = decode_real(in);
- break;
- case ITEM_BLOB:
- element = decode_blob(in, item_length);
- break;
- case ITEM_UTF8:
- // XXXMLG currently identical to decode_blob
- element = decode_blob(in, item_length);
- break;
- case ITEM_HASH:
- element = decode_hash(in, item_length);
- break;
- case ITEM_LIST:
- element = decode_list(in, item_length);
- break;
- case ITEM_NULL:
- element = decode_null();
- break;
- }
-
- return (element);
-}
-}
-
ElementPtr
Element::fromWire(const std::string& s) {
std::stringstream ss;
ss << s;
- return fromWire(ss, s.length());
+ int line = 0, pos = 0;
+ return fromJSON(ss, "<wire>", line, pos);
}
ElementPtr
@@ -804,159 +726,20 @@
//
// Check protocol version
//
- for (int i = 0 ; i < 4 ; ++i) {
- const unsigned char version_byte = get_byte(in);
- if (PROTOCOL_VERSION[i] != version_byte) {
- throw DecodeError("Protocol version incorrect");
- }
- }
- length -= 4;
-
- return (decode_hash(in, length));
-}
-
-//
-// Encode into wire format.
-//
-
-std::string
-encode_length(const unsigned int length, unsigned char type) {
- std::stringstream ss;
-
- if (length <= 0x000000ff) {
- const unsigned char val = (length & 0x000000ff);
- type |= ITEM_LENGTH_8;
- ss << type << val;
- } else if (length <= 0x0000ffff) {
- unsigned char val[2];
- val[0] = (length & 0x0000ff00) >> 8;
- val[1] = (length & 0x000000ff);
- type |= ITEM_LENGTH_16;
- ss << type << val[0] << val[1];
- } else {
- unsigned char val[4];
- val[0] = (length & 0xff000000) >> 24;
- val[1] = (length & 0x00ff0000) >> 16;
- val[2] = (length & 0x0000ff00) >> 8;
- val[3] = (length & 0x000000ff);
- type |= ITEM_LENGTH_32;
- ss << type << val[0] << val[1] << val[2] << val[3];
- }
- return ss.str();
-}
-
-std::string
-Element::toWire(const int omit_length) {
- std::stringstream ss;
- toWire(ss, omit_length);
- return ss.str();
-}
-
-void
-StringElement::toWire(std::stringstream& ss,
- const int omit_length UNUSED_PARAM)
-{
- unsigned int length = stringValue().length();
- ss << encode_length(length, ITEM_UTF8) << stringValue();
-}
-
-void
-IntElement::toWire(std::stringstream& ss,
- const int omit_length UNUSED_PARAM)
-{
- const std::string& s = str();
- ss << encode_length(s.length(), ITEM_INT) << s;
-}
-
-void
-BoolElement::toWire(std::stringstream& ss,
- const int omit_length UNUSED_PARAM)
-{
- ss << encode_length(1, ITEM_BOOL);
- if (boolValue()) {
- ss << '1';
- } else {
- ss << '0';
- }
-}
-
-void
-DoubleElement::toWire(std::stringstream& ss,
- const int omit_length UNUSED_PARAM)
-{
- std::stringstream text;
-
- text << str();
- const int length = text.str().length();
- ss << encode_length(length, ITEM_REAL) << text.str();
-}
-
-void
-ListElement::toWire(std::stringstream& ss, const int omit_length) {
- std::stringstream ss2;
- const std::vector<ElementPtr>& v = listValue();
- for (std::vector<ElementPtr>::const_iterator it = v.begin() ;
- it != v.end() ; ++it) {
- (*it)->toWire(ss2, 0);
- }
-
-
- if (omit_length) {
- stringbuf *ss2_buf = ss2.rdbuf();
- ss2_buf->pubseekpos(0);
- if (ss2_buf->in_avail() > 0) {
- ss << ss2_buf;
- }
- } else {
- stringbuf *ss2_buf = ss2.rdbuf();
- ss2_buf->pubseekpos(0);
- ss << encode_length(ss2_buf->in_avail(), ITEM_LIST);
- if (ss2_buf->in_avail() > 0) {
- ss << ss2_buf;
- }
- }
-}
-
-void
-MapElement::toWire(std::stringstream& ss, int omit_length) {
- std::stringstream ss2;
-
- //
- // If we don't want the length, we will want the protocol header
- //
- if (omit_length) {
- ss2 << PROTOCOL_VERSION[0] << PROTOCOL_VERSION[1];
- ss2 << PROTOCOL_VERSION[2] << PROTOCOL_VERSION[3];
- }
-
- const std::map<std::string, ElementPtr>& m = mapValue();
- for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
- it != m.end(); ++it) {
- const size_t taglen = (*it).first.length();
- assert(taglen <= 0xff);
- const unsigned char val = (taglen & 0x000000ff);
- ss2 << val << (*it).first;
-
- (*it).second->toWire(ss2, 0);
- }
-
- //
- // add length if needed
- //
- if (omit_length) {
- stringbuf *ss2_buf = ss2.rdbuf();
- ss2_buf->pubseekpos(0);
- if (ss2_buf->in_avail()) {
- ss << ss2_buf;
- }
- } else {
- stringbuf *ss2_buf = ss2.rdbuf();
- ss2_buf->pubseekpos(0);
- ss << encode_length(ss2_buf->in_avail(), ITEM_HASH);
- if (ss2_buf->in_avail()) {
- ss << ss2_buf;
- }
- }
+ //for (int i = 0 ; i < 4 ; ++i) {
+ // const unsigned char version_byte = get_byte(in);
+ // if (PROTOCOL_VERSION[i] != version_byte) {
+ // throw DecodeError("Protocol version incorrect");
+ // }
+ //}
+ //length -= 4;
+ int line = 0, pos = 0;
+ return fromJSON(in, "<wire>", line, pos);
+}
+
+void
+MapElement::set(const std::string& key, ElementPtr value) {
+ m[key] = value;
}
bool
@@ -989,6 +772,11 @@
BoolElement::equals(ElementPtr other) {
return (other->getType() == Element::boolean) &&
(b == other->boolValue());
+}
+
+bool
+NullElement::equals(ElementPtr other) {
+ return other->getType() == Element::null;
}
bool
@@ -1082,7 +870,7 @@
std::map<std::string, ElementPtr> m = other->mapValue();
for (std::map<std::string, ElementPtr>::const_iterator it = m.begin();
it != m.end() ; ++it) {
- if ((*it).second) {
+ if ((*it).second && (*it).second->getType() != Element::null) {
element->set((*it).first, (*it).second);
} else if (element->contains((*it).first)) {
element->remove((*it).first);
Modified: trunk/src/lib/cc/data.h
==============================================================================
--- trunk/src/lib/cc/data.h (original)
+++ trunk/src/lib/cc/data.h Wed Jun 30 19:05:31 2010
@@ -48,22 +48,10 @@
// i'd like to use Exception here but we need one that is derived from
// runtime_error (as this one is directly based on external data, and
// i want to add some values to any static data string that is provided)
-class ParseError : public std::runtime_error {
-public:
- ParseError(const std::string &err) : std::runtime_error(err) {};
-};
-
-///
-/// \brief A standard Data module exception that is thrown if an error
-/// is found when decoding an Element from wire format
-///
-class DecodeError : public std::exception {
-public:
- DecodeError(std::string m = "Wire-format data is invalid") : msg(m) {}
- ~DecodeError() throw() {}
- const char* what() const throw() { return msg.c_str(); }
-private:
- std::string msg;
+class JSONError : public isc::Exception {
+public:
+ JSONError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) {}
};
///
@@ -75,7 +63,7 @@
///
/// Elements should in calling functions usually be referenced through
/// an \c ElementPtr, which can be created using the factory functions
-/// \c Element::create() and \c Element::createFromString()
+/// \c Element::create() and \c Element::fromJSON()
///
/// Notes to developers: Element is a base class, implemented by a
/// specific subclass for each type (IntElement, BoolElement, etc).
@@ -97,40 +85,40 @@
public:
// any is a special type used in list specifications, specifying
// that the elements can be of any type
- enum types { integer, real, boolean, string, list, map, any };
+ enum types { integer, real, boolean, null, string, list, map, any };
// base class; make dtor virtual
virtual ~Element() {};
/// \return the type of this element
int getType() { return type; };
+
+ /// Returns a string representing the Element and all its
+ /// child elements; note that this is different from stringValue(),
+ /// which only returns the single value of a StringElement
+ ///
+ /// The resulting string will contain the Element in JSON format.
+ ///
+ /// \return std::string containing the string representation
+ std::string str();
+
+ /// Returns the wireformat for the Element and all its child
+ /// elements.
+ ///
+ /// \return std::string containing the element in wire format
+ std::string toWire();
+ void toWire(std::ostream& out);
+
+ /// \name pure virtuals, every derived class must implement these
/// \returns true if the other ElementPtr has the same type and
/// value
virtual bool equals(ElementPtr other) = 0;
- // pure virtuals, every derived class must implement these
-
- /// Returns a string representing the Element and all its
- /// child elements; note that this is different from stringValue(),
- /// which only returns the single value of a StringElement
- /// A MapElement will be represented as { "name1": \<value1\>, "name2", \<value2\>, etc }
- /// A ListElement will be represented as [ \<item1\>, \<item2\>, etc ]
- /// All other elements will be represented directly
- ///
- /// \return std::string containing the string representation
- virtual std::string str() = 0;
-
- /// Returns the wireformat for the Element and all its child
- /// elements.
- ///
- /// \param omit_length If this is non-zero, the item length will
- /// be omitted from the wire format
- /// \return std::string containing the element in wire format
- std::string toWire(int omit_length = 1);
- virtual void toWire(std::stringstream& out, int omit_length = 1) = 0;
+ /// Converts the Element to JSON format and appends it to
+ /// the given stringstream.
+ virtual void toJSON(std::ostream& ss) = 0;
/// \name Type-specific getters
- ///
///
/// \brief These functions only
/// work on their corresponding Element type. For all other
@@ -138,7 +126,7 @@
/// If you want an exception-safe getter method, use
/// getValue() below
//@{
- virtual int intValue() { isc_throw(TypeError, "intValue() called on non-integer Element"); };
+ virtual long int intValue() { isc_throw(TypeError, "intValue() called on non-integer Element"); };
virtual double doubleValue() { isc_throw(TypeError, "doubleValue() called on non-double Element"); };
virtual bool boolValue() { isc_throw(TypeError, "boolValue() called on non-Bool Element"); };
virtual std::string stringValue() { isc_throw(TypeError, "stringValue() called on non-string Element"); };
@@ -155,13 +143,14 @@
/// data to the given reference and returning true
///
//@{
- virtual bool getValue(int& t);
+ virtual bool getValue(long int& t);
virtual bool getValue(double& t);
virtual bool getValue(bool& t);
virtual bool getValue(std::string& t);
virtual bool getValue(std::vector<ElementPtr>& t);
virtual bool getValue(std::map<std::string, ElementPtr>& t);
//@}
+
///
/// \name Exception-safe setters.
///
@@ -170,7 +159,7 @@
/// is of the correct type
///
//@{
- virtual bool setValue(const int v);
+ virtual bool setValue(const long int v);
virtual bool setValue(const double v);
virtual bool setValue(const bool t);
virtual bool setValue(const std::string& v);
@@ -191,21 +180,26 @@
/// of bounds, this function throws an std::out_of_range exception.
/// \param i The position of the ElementPtr to return
virtual ElementPtr get(const int i);
+
/// Sets the ElementPtr at the given index. If the index is out
/// of bounds, this function throws an std::out_of_range exception.
/// \param i The position of the ElementPtr to set
/// \param element The ElementPtr to set at the position
virtual void set(const size_t i, ElementPtr element);
+
/// Adds an ElementPtr to the list
/// \param element The ElementPtr to add
virtual void add(ElementPtr element);
+
/// Removes the element at the given position. If the index is out
/// of nothing happens.
/// \param i The index of the element to remove.
virtual void remove(const int i);
+
/// Returns the number of elements in the list.
virtual size_t size();
//@}
+
/// \name MapElement functions
///
@@ -216,16 +210,20 @@
/// \param name The key of the Element to return
/// \return The ElementPtr at the given key
virtual ElementPtr get(const std::string& name);
+
/// Sets the ElementPtr at the given key
/// \param name The key of the Element to set
virtual void set(const std::string& name, ElementPtr element);
+
/// Remove the ElementPtr at the given key
/// \param name The key of the Element to remove
virtual void remove(const std::string& name);
+
/// Checks if there is data at the given key
/// \param name The key of the Element to remove
/// \return true if there is data at the key, false if not.
virtual bool contains(const std::string& name);
+
/// Recursively finds any data at the given identifier. The
/// identifier is a /-separated list of names of nested maps, with
/// the last name being the leaf that is returned.
@@ -240,6 +238,7 @@
/// null ElementPtr if it is not found, which can be checked with
/// Element::is_null(ElementPtr e).
virtual ElementPtr find(const std::string& identifier);
+
/// See \c Element::find()
/// \param identifier The identifier of the element to find
/// \param t Reference to store the resulting ElementPtr, if found.
@@ -247,6 +246,7 @@
virtual bool find(const std::string& identifier, ElementPtr& t);
//@}
+
/// \name Factory functions
// TODO: should we move all factory functions to a different class
@@ -257,39 +257,52 @@
/// \brief These functions simply wrap the given data directly
/// in an Element object, and return a reference to it, in the form
/// of an \c ElementPtr.
- /// If there is a memory allocation problem, these functions will
- /// return a NULL ElementPtr, which can be checked with
- /// Element::is_null(ElementPtr ep).
- //@{
- static ElementPtr create(const int i);
+ /// These factory functions are exception-free (unless there is
+ /// no memory available, in which case bad_alloc is raised by the
+ /// underlying system).
+ /// (Note that that is different from an NullElement, which
+ /// represents an empty value, and is created with Element::create())
+ //@{
+ static ElementPtr create();
+ static ElementPtr create(const long int i);
+ static ElementPtr create(const int i) { return create(static_cast<long int>(i)); };
static ElementPtr create(const double d);
static ElementPtr create(const bool b);
static ElementPtr create(const std::string& s);
// need both std:string and char *, since c++ will match
// bool before std::string when you pass it a char *
- static ElementPtr create(const char *s) { return create(std::string(s)); };
- static ElementPtr create(const std::vector<ElementPtr>& v);
- static ElementPtr create(const std::map<std::string, ElementPtr>& m);
- //@}
+ static ElementPtr create(const char *s) { return create(std::string(s)); };
+
+ /// \brief Creates an empty ListElement type ElementPtr.
+ static ElementPtr createList();
+
+ /// \brief Creates an empty MapElement type ElementPtr.
+ static ElementPtr createMap();
+ //@}
+
/// \name Compound factory functions
- /// \brief These functions will parse the given string representation
- /// of a compound element. If there is a parse error, an exception
- /// of the type isc::data::ParseError is thrown.
-
- //@{
- /// Creates an Element from the given string
+ /// \brief These functions will parse the given string (JSON)
+ /// representation of a compound element. If there is a parse
+ /// error, an exception of the type isc::data::JSONError is thrown.
+
+ //@{
+ /// Creates an Element from the given JSON string
/// \param in The string to parse the element from
/// \return An ElementPtr that contains the element(s) specified
/// in the given string.
- static ElementPtr createFromString(const std::string& in);
- /// Creates an Element from the given input stream
+ static ElementPtr fromJSON(const std::string& in);
+
+ /// Creates an Element from the given input stream containing JSON
+ /// formatted data.
+ ///
/// \param in The string to parse the element from
/// \return An ElementPtr that contains the element(s) specified
/// in the given input stream.
- static ElementPtr createFromString(std::istream& in) throw(ParseError);
- static ElementPtr createFromString(std::istream& in, const std::string& file_name) throw(ParseError);
+ static ElementPtr fromJSON(std::istream& in) throw(JSONError);
+ static ElementPtr fromJSON(std::istream& in, const std::string& file_name) throw(JSONError);
+
/// Creates an Element from the given input stream, where we keep
/// track of the location in the stream for error reporting.
///
@@ -301,8 +314,24 @@
/// \return An ElementPtr that contains the element(s) specified
/// in the given input stream.
// make this one private?
- static ElementPtr createFromString(std::istream& in, const std::string& file, int& line, int &pos) throw(ParseError);
- //@}
+ static ElementPtr fromJSON(std::istream& in, const std::string& file, int& line, int &pos) throw(JSONError);
+ //@}
+
+ /// \name Type name conversion functions
+
+ /// Returns the name of the given type as a string
+ ///
+ /// \param type The type to return the name of
+ /// \return The name of the type, or "unknown" if the type
+ /// is not known.
+ static std::string typeToName(Element::types type);
+
+ /// Converts the string to the corresponding type
+ /// Throws a TypeError if the name is unknown.
+ ///
+ /// \param type_name The name to get the type of
+ /// \return the corresponding type value
+ static Element::types nameToType(const std::string& type_name);
/// \name Wire format factory functions
@@ -313,11 +342,18 @@
//@{
/// Creates an Element from the wire format in the given
/// stringstream of the given length.
+ /// Since the wire format is JSON, thise is the same as
+ /// fromJSON, and could be removed.
+ ///
/// \param in The input stringstream.
/// \param length The length of the wireformat data in the stream
/// \return ElementPtr with the data that is parsed.
static ElementPtr fromWire(std::stringstream& in, int length);
+
/// Creates an Element from the wire format in the given string
+ /// Since the wire format is JSON, thise is the same as
+ /// fromJSON, and could be removed.
+ ///
/// \param s The input string
/// \return ElementPtr with the data that is parsed.
static ElementPtr fromWire(const std::string& s);
@@ -325,17 +361,16 @@
};
class IntElement : public Element {
- int i;
-
-public:
- IntElement(int v) : Element(integer), i(v) { };
- int intValue() { return i; }
+ long int i;
+
+public:
+ IntElement(long int v) : Element(integer), i(v) { };
+ long int intValue() { return i; }
using Element::getValue;
- bool getValue(int& t) { t = i; return true; };
+ bool getValue(long int& t) { t = i; return true; };
using Element::setValue;
- bool setValue(const int v) { i = v; return true; };
- std::string str();
- void toWire(std::stringstream& ss, int omit_length = 1);
+ bool setValue(const long int v) { i = v; return true; };
+ void toJSON(std::ostream& ss);
bool equals(ElementPtr other);
};
@@ -349,8 +384,7 @@
bool getValue(double& t) { t = d; return true; };
using Element::setValue;
bool setValue(const double v) { d = v; return true; };
- std::string str();
- void toWire(std::stringstream& ss, int omit_length = 1);
+ void toJSON(std::ostream& ss);
bool equals(ElementPtr other);
};
@@ -364,8 +398,14 @@
bool getValue(bool& t) { t = b; return true; };
using Element::setValue;
bool setValue(const bool v) { b = v; return true; };
- std::string str();
- void toWire(std::stringstream& ss, int omit_length = 1);
+ void toJSON(std::ostream& ss);
+ bool equals(ElementPtr other);
+};
+
+class NullElement : public Element {
+public:
+ NullElement() : Element(null) {};
+ void toJSON(std::ostream& ss);
bool equals(ElementPtr other);
};
@@ -379,8 +419,7 @@
bool getValue(std::string& t) { t = s; return true; };
using Element::setValue;
bool setValue(const std::string& v) { s = v; return true; };
- std::string str();
- void toWire(std::stringstream& ss, int omit_length = 1);
+ void toJSON(std::ostream& ss);
bool equals(ElementPtr other);
};
@@ -388,7 +427,7 @@
std::vector<ElementPtr> l;
public:
- ListElement(std::vector<ElementPtr> v) : Element(list), l(v) {};
+ ListElement() : Element(list), l(std::vector<ElementPtr>()) {};
const std::vector<ElementPtr>& listValue() { return l; }
using Element::getValue;
bool getValue(std::vector<ElementPtr>& t) { t = l; return true; };
@@ -401,8 +440,7 @@
void add(ElementPtr e) { l.push_back(e); };
using Element::remove;
void remove(int i) { l.erase(l.begin() + i); };
- std::string str();
- void toWire(std::stringstream& ss, int omit_length = 1);
+ void toJSON(std::ostream& ss);
size_t size() { return l.size(); }
bool equals(ElementPtr other);
};
@@ -411,7 +449,8 @@
std::map<std::string, ElementPtr> m;
public:
- MapElement(const std::map<std::string, ElementPtr>& v) : Element(map), m(v) {};
+ MapElement() : Element(map), m(std::map<std::string, ElementPtr>()) {};
+ // TODO: should we have direct iterators instead of exposing the std::map here?
const std::map<std::string, ElementPtr>& mapValue() { return m; }
using Element::getValue;
bool getValue(std::map<std::string, ElementPtr>& t) { t = m; return true; };
@@ -420,18 +459,12 @@
using Element::get;
ElementPtr get(const std::string& s) { if (contains(s)) { return m[s]; } else { return ElementPtr();} };
using Element::set;
- void set(const std::string& s, ElementPtr p) { m[s] = p; };
+ void set(const std::string& key, ElementPtr value);
using Element::remove;
void remove(const std::string& s) { m.erase(s); }
bool contains(const std::string& s) { return m.find(s) != m.end(); }
- std::string str();
- void toWire(std::stringstream& ss, int omit_length = 1);
+ void toJSON(std::ostream& ss);
- //
- // Encode into the CC wire format.
- //
- void toWire(std::ostream& ss);
-
// we should name the two finds better...
// find the element at id; raises TypeError if one of the
// elements at path except the one we're looking for is not a
@@ -467,8 +500,12 @@
/// MapElements.
/// Every string,value pair in other is copied into element
/// (the ElementPtr of value is copied, this is not a new object)
-/// Unless the value is an empty ElementPtr, in which case the
-/// whole key is removed from element.
+/// Unless the value is a NullElement, in which case the
+/// key is removed from element, rather than setting the value to
+/// the given NullElement.
+/// This way, we can remove values from for instance maps with
+/// configuration data (which would then result in reverting back
+/// to the default).
/// Raises a TypeError if either ElementPtr is not a MapElement
void merge(ElementPtr element, const ElementPtr other);
Modified: trunk/src/lib/cc/data_unittests.cc
==============================================================================
--- trunk/src/lib/cc/data_unittests.cc (original)
+++ trunk/src/lib/cc/data_unittests.cc Wed Jun 30 19:05:31 2010
@@ -40,58 +40,124 @@
EXPECT_EQ(bool_el.getType(), Element::boolean);
StringElement str_el = StringElement("foo");
EXPECT_EQ(str_el.getType(), Element::string);
- std::vector<ElementPtr> v;
- ListElement list_el = ListElement(v);
+ ListElement list_el = ListElement();
EXPECT_EQ(list_el.getType(), Element::list);
- std::map<std::string, ElementPtr> m;
- MapElement map_el = MapElement(m);
+ MapElement map_el = MapElement();
EXPECT_EQ(map_el.getType(), Element::map);
-}
-
-TEST(Element, from_and_to_str) {
- // this test checks whether the str() method returns the same
- // string that was used for creation
+
+}
+
+TEST(Element, TypeNameConversion) {
+ EXPECT_EQ(Element::integer, Element::nameToType("integer"));
+ EXPECT_EQ(Element::real, Element::nameToType("real"));
+ EXPECT_EQ(Element::boolean, Element::nameToType("boolean"));
+ EXPECT_EQ(Element::string, Element::nameToType("string"));
+ EXPECT_EQ(Element::list, Element::nameToType("list"));
+ EXPECT_EQ(Element::map, Element::nameToType("map"));
+ EXPECT_EQ(Element::null, Element::nameToType("null"));
+ EXPECT_EQ(Element::any, Element::nameToType("any"));
+ EXPECT_THROW(Element::nameToType("somethingunknown"), TypeError);
+
+ EXPECT_EQ("integer", Element::typeToName(Element::integer));
+ EXPECT_EQ("real", Element::typeToName(Element::real));
+ EXPECT_EQ("boolean", Element::typeToName(Element::boolean));
+ EXPECT_EQ("string", Element::typeToName(Element::string));
+ EXPECT_EQ("list", Element::typeToName(Element::list));
+ EXPECT_EQ("map", Element::typeToName(Element::map));
+ EXPECT_EQ("null", Element::typeToName(Element::null));
+ EXPECT_EQ("any", Element::typeToName(Element::any));
+ EXPECT_EQ("unknown", Element::typeToName((Element::types)123));
+}
+
+TEST(Element, from_and_to_json) {
+ // a set of inputs that are the same when converted to json and
+ // back to a string (tests for inputs that have equivalent, but
+ // different string representations when converted back are below)
ElementPtr el;
std::vector<std::string> sv;
sv.push_back("12");
sv.push_back("1.1");
- sv.push_back("True");
- sv.push_back("False");
+ sv.push_back("true");
+ sv.push_back("false");
sv.push_back("\"asdf\"");
+ sv.push_back("null");
sv.push_back("[ 1, 2, 3, 4 ]");
- sv.push_back("{\"name\": \"foo\", \"value\": 47806}");
- sv.push_back("[ {\"a\": 1, \"b\": \"c\"}, {\"a\": 2, \"b\": \"d\"} ]");
-
+ sv.push_back("{ \"name\": \"foo\", \"value\": 47806 }");
+ sv.push_back("[ { \"a\": 1, \"b\": \"c\" }, { \"a\": 2, \"b\": \"d\" } ]");
+ sv.push_back("8.23");
+ sv.push_back("123.456");
+ sv.push_back("null");
+ sv.push_back("-1");
+ sv.push_back("-1.234");
+ sv.push_back("-123.456");
+
BOOST_FOREACH(std::string s, sv) {
- // also test << operator, which uses Element::str()
+ // test << operator, which uses Element::str()
std::ostringstream stream;
- el = Element::createFromString(s);
+ el = Element::fromJSON(s);
stream << el;
EXPECT_EQ(stream.str(), s);
+
+ // test toWire(ostream), which should also be the same now
+ std::ostringstream wire_stream;
+ el->toWire(wire_stream);
+ EXPECT_EQ(wire_stream.str(), s);
}
// some parse errors
try {
- Element::createFromString("{1}");
- } catch (isc::data::ParseError pe) {
+ Element::fromJSON("{1}");
+ } catch (isc::data::JSONError pe) {
std::string s = std::string(pe.what());
EXPECT_EQ(s, "String expected in <string>:1:3");
}
sv.clear();
sv.push_back("{1}");
- //ElementPtr ep = Element::createFromString("\"aaa\nbbb\"err");
+ //ElementPtr ep = Element::fromJSON("\"aaa\nbbb\"err");
//std::cout << ep << std::endl;
sv.push_back("\n\nTru");
sv.push_back("{ \n \"aaa\nbbb\"err:");
sv.push_back("{ \t\n \"aaa\nbbb\"\t\n\n:\n True, \"\\\"");
sv.push_back("{ \"a\": None}");
sv.push_back("");
+ sv.push_back("nul");
BOOST_FOREACH(std::string s, sv) {
- EXPECT_THROW(el = Element::createFromString(s), isc::data::ParseError);
+ EXPECT_THROW(el = Element::fromJSON(s), isc::data::JSONError);
}
+
+ // some json specific format tests, here the str() output is
+ // different from the string input
+ EXPECT_EQ("100", Element::fromJSON("+100")->str());
+ EXPECT_EQ("100", Element::fromJSON("1e2")->str());
+ EXPECT_EQ("100", Element::fromJSON("+1e2")->str());
+ EXPECT_EQ("-100", Element::fromJSON("-1e2")->str());
+ EXPECT_EQ("0.01", Element::fromJSON("1e-2")->str());
+ EXPECT_EQ("0.01", Element::fromJSON(".01")->str());
+ EXPECT_EQ("-0.01", Element::fromJSON("-1e-2")->str());
+ EXPECT_EQ("1.2", Element::fromJSON("1.2")->str());
+ EXPECT_EQ("1", Element::fromJSON("1.0")->str());
+ EXPECT_EQ("120", Element::fromJSON("1.2e2")->str());
+ EXPECT_EQ("100", Element::fromJSON("1.0e2")->str());
+ EXPECT_EQ("100", Element::fromJSON("1.0E2")->str());
+ EXPECT_EQ("0.01", Element::fromJSON("1.0e-2")->str());
+ EXPECT_EQ("0.012", Element::fromJSON("1.2e-2")->str());
+ EXPECT_EQ("0.012", Element::fromJSON("1.2E-2")->str());
+ EXPECT_EQ("null", Element::fromJSON("Null")->str());
+ EXPECT_EQ("null", Element::fromJSON("NULL")->str());
+ EXPECT_EQ("false", Element::fromJSON("False")->str());
+ EXPECT_EQ("false", Element::fromJSON("FALSE")->str());
+ EXPECT_EQ("true", Element::fromJSON("True")->str());
+ EXPECT_EQ("true", Element::fromJSON("TRUE")->str());
+
+ // number overflows
+ EXPECT_THROW(Element::fromJSON("12345678901234567890")->str(), JSONError);
+ EXPECT_THROW(Element::fromJSON("1.1e12345678901234567890")->str(), JSONError);
+ EXPECT_THROW(Element::fromJSON("-1.1e12345678901234567890")->str(), JSONError);
+ EXPECT_THROW(Element::fromJSON("1e12345678901234567890")->str(), JSONError);
+ EXPECT_THROW(Element::fromJSON("1e50000")->str(), JSONError);
}
@@ -99,61 +165,150 @@
// this test checks whether elements throw exceptions if the
// incorrect type is requested
ElementPtr el;
+ long int i;
+ double d;
+ bool b;
+ std::string s("asdf");
+ std::vector<ElementPtr> v;
+ std::map<std::string, ElementPtr> m;
+
el = Element::create(1);
+ EXPECT_NO_THROW(el->intValue());
EXPECT_THROW(el->doubleValue(), TypeError);
EXPECT_THROW(el->boolValue(), TypeError);
EXPECT_THROW(el->stringValue(), TypeError);
EXPECT_THROW(el->listValue(), TypeError);
EXPECT_THROW(el->mapValue(), TypeError);
+ EXPECT_TRUE(el->getValue(i));
+ EXPECT_FALSE(el->getValue(d));
+ EXPECT_FALSE(el->getValue(b));
+ EXPECT_FALSE(el->getValue(s));
+ EXPECT_FALSE(el->getValue(v));
+ EXPECT_FALSE(el->getValue(m));
+ EXPECT_EQ(i, 1);
+ i = 2;
+ EXPECT_TRUE(el->setValue(i));
+ EXPECT_EQ(2, el->intValue());
+ EXPECT_FALSE(el->setValue(d));
+ EXPECT_FALSE(el->setValue(b));
+ EXPECT_FALSE(el->setValue(s));
+ EXPECT_FALSE(el->setValue(v));
+ EXPECT_FALSE(el->setValue(m));
+ EXPECT_THROW(el->get(1), TypeError);
+ EXPECT_THROW(el->set(1, el), TypeError);
+ EXPECT_THROW(el->add(el), TypeError);
+ EXPECT_THROW(el->remove(1), TypeError);
+ EXPECT_THROW(el->size(), TypeError);
+ EXPECT_THROW(el->get("foo"), TypeError);
+ EXPECT_THROW(el->set("foo", el), TypeError);
+ EXPECT_THROW(el->remove("foo"), TypeError);
+ EXPECT_THROW(el->contains("foo"), TypeError);
+ ElementPtr tmp;
+ EXPECT_FALSE(el->find("foo", tmp));
+
el = Element::create(1.1);
EXPECT_THROW(el->intValue(), TypeError);
+ EXPECT_NO_THROW(el->doubleValue());
EXPECT_THROW(el->boolValue(), TypeError);
EXPECT_THROW(el->stringValue(), TypeError);
EXPECT_THROW(el->listValue(), TypeError);
EXPECT_THROW(el->mapValue(), TypeError);
+ EXPECT_FALSE(el->getValue(i));
+ EXPECT_TRUE(el->getValue(d));
+ EXPECT_FALSE(el->getValue(b));
+ EXPECT_FALSE(el->getValue(s));
+ EXPECT_FALSE(el->getValue(v));
+ EXPECT_FALSE(el->getValue(m));
+ EXPECT_EQ(d, 1.1);
+ d = 2.2;
+ EXPECT_TRUE(el->setValue(d));
+ EXPECT_EQ(2.2, el->doubleValue());
+ EXPECT_FALSE(el->setValue(i));
+ EXPECT_FALSE(el->setValue(b));
+ EXPECT_FALSE(el->setValue(s));
+ EXPECT_FALSE(el->setValue(v));
+ EXPECT_FALSE(el->setValue(m));
el = Element::create(true);
EXPECT_THROW(el->intValue(), TypeError);
EXPECT_THROW(el->doubleValue(), TypeError);
+ EXPECT_NO_THROW(el->boolValue());
EXPECT_THROW(el->stringValue(), TypeError);
EXPECT_THROW(el->listValue(), TypeError);
EXPECT_THROW(el->mapValue(), TypeError);
+ EXPECT_FALSE(el->getValue(i));
+ EXPECT_FALSE(el->getValue(d));
+ EXPECT_TRUE(el->getValue(b));
+ EXPECT_FALSE(el->getValue(s));
+ EXPECT_FALSE(el->getValue(v));
+ EXPECT_FALSE(el->getValue(m));
+ EXPECT_EQ(b, true);
+ b = false;
+ EXPECT_TRUE(el->setValue(b));
+ EXPECT_EQ(false, el->boolValue());
el = Element::create("foo");
EXPECT_THROW(el->intValue(), TypeError);
EXPECT_THROW(el->doubleValue(), TypeError);
EXPECT_THROW(el->boolValue(), TypeError);
+ EXPECT_NO_THROW(el->stringValue());
EXPECT_THROW(el->listValue(), TypeError);
EXPECT_THROW(el->mapValue(), TypeError);
-
- std::vector<ElementPtr> v;
- el = Element::create(v);
+ EXPECT_FALSE(el->getValue(i));
+ EXPECT_FALSE(el->getValue(d));
+ EXPECT_FALSE(el->getValue(b));
+ EXPECT_TRUE(el->getValue(s));
+ EXPECT_FALSE(el->getValue(v));
+ EXPECT_FALSE(el->getValue(m));
+ EXPECT_EQ(s, "foo");
+ s = "bar";
+ EXPECT_TRUE(el->setValue(s));
+ EXPECT_EQ("bar", el->stringValue());
+
+ el = Element::createList();
EXPECT_THROW(el->intValue(), TypeError);
EXPECT_THROW(el->doubleValue(), TypeError);
EXPECT_THROW(el->boolValue(), TypeError);
EXPECT_THROW(el->stringValue(), TypeError);
+ EXPECT_NO_THROW(el->listValue());
EXPECT_THROW(el->mapValue(), TypeError);
-
- std::map<std::string, ElementPtr> m;
- el = Element::create(m);
+ EXPECT_FALSE(el->getValue(i));
+ EXPECT_FALSE(el->getValue(d));
+ EXPECT_FALSE(el->getValue(b));
+ EXPECT_FALSE(el->getValue(s));
+ EXPECT_TRUE(el->getValue(v));
+ EXPECT_FALSE(el->getValue(m));
+ EXPECT_EQ("[ ]", el->str());
+ v.push_back(Element::create(1));
+ EXPECT_TRUE(el->setValue(v));
+ EXPECT_EQ("[ 1 ]", el->str());
+
+ el = Element::createMap();
EXPECT_THROW(el->intValue(), TypeError);
EXPECT_THROW(el->doubleValue(), TypeError);
EXPECT_THROW(el->boolValue(), TypeError);
EXPECT_THROW(el->stringValue(), TypeError);
EXPECT_THROW(el->listValue(), TypeError);
+ EXPECT_NO_THROW(el->mapValue());
+ EXPECT_FALSE(el->getValue(i));
+ EXPECT_FALSE(el->getValue(d));
+ EXPECT_FALSE(el->getValue(b));
+ EXPECT_FALSE(el->getValue(s));
+ EXPECT_FALSE(el->getValue(v));
+ EXPECT_TRUE(el->getValue(m));
}
TEST(Element, ListElement) {
// this function checks the specific functions for ListElements
- ElementPtr el = Element::createFromString("[ 1, \"bar\", 3 ]");
+ ElementPtr el = Element::fromJSON("[ 1, \"bar\", 3 ]");
EXPECT_EQ(el->get(0)->intValue(), 1);
EXPECT_EQ(el->get(1)->stringValue(), "bar");
EXPECT_EQ(el->get(2)->intValue(), 3);
- el->set(0, Element::createFromString("\"foo\""));
+ el->set(0, Element::fromJSON("\"foo\""));
EXPECT_EQ(el->get(0)->stringValue(), "foo");
el->add(Element::create(47806));
@@ -170,18 +325,9 @@
EXPECT_EQ(el->get(2)->intValue(), 32);
}
-namespace {
-const string long_maptag("0123456789abcdef1123456789abcdef2123456789abcdef"
- "3123456789abcdef4123456789abcdef5123456789abcdef"
- "6123456789abcdef7123456789abcdef8123456789abcdef"
- "9123456789abcdefa123456789abcdefb123456789abcdef"
- "c123456789abcdefd123456789abcdefe123456789abcdef"
- "f123456789abcdef");
-}
-
TEST(Element, MapElement) {
// this function checks the specific functions for ListElements
- ElementPtr el = Element::createFromString("{ \"name\": \"foo\", \"value1\": \"bar\", \"value2\": { \"number\": 42 } }");
+ ElementPtr el = Element::fromJSON("{ \"name\": \"foo\", \"value1\": \"bar\", \"value2\": { \"number\": 42 } }");
ElementPtr el2;
EXPECT_EQ(el->get("name")->stringValue(), "foo");
@@ -211,240 +357,241 @@
"9123456789abcdefa123456789abcdefb123456789abcdef"
"c123456789abcdefd123456789abcdefe123456789abcdef"
"f123456789abcde");
- std::map<std::string, ElementPtr> long_maptag_map;
EXPECT_EQ(255, long_maptag.length()); // check prerequisite
- el = Element::createFromString("{ \"" + long_maptag + "\": \"bar\"}");
+ el = Element::fromJSON("{ \"" + long_maptag + "\": \"bar\"}");
EXPECT_EQ("bar", el->find(long_maptag)->stringValue());
- long_maptag_map[long_maptag] = Element::create("bar");
- el = Element::create(long_maptag_map);
+ el = Element::createMap();
+ el->set(long_maptag, Element::create("bar"));
EXPECT_EQ("bar", el->find(long_maptag)->stringValue());
- // A one-byte longer tag should trigger an exception.
+ // A one-byte longer tag should still be allowed
long_maptag.push_back('f');
- EXPECT_THROW(Element::createFromString("{ \"" + long_maptag +
- "\": \"bar\"}"),
- ParseError);
-
- long_maptag_map[long_maptag] = Element::create("bar");
- EXPECT_THROW(Element::create(long_maptag_map), TypeError);
+ el = Element::fromJSON("{ \"" + long_maptag + "\": \"bar\"}");
+ el->set(long_maptag, Element::create("bar"));
+ EXPECT_EQ("bar", el->find(long_maptag)->stringValue());
}
TEST(Element, to_and_from_wire) {
- ElementPtr el, decoded_el;
- std::string wire;
- std::vector<std::string> sv;
- std::vector<std::string> sw;
- std::stringstream bigstring, bigstring2;
- std::stringstream bigwire, bigwire2;
-
- sv.push_back("{\"name\": \"foo\"}");
- sw.push_back("Skan\004name\050\003foo");
- sv.push_back("{\"value2\": {\"number\": 42}}");
- sw.push_back("Skan\006value2\042\013\006number\046\00242");
- sv.push_back("{\"bool\": False, \"bool2\": True, \"real\": 2.34, \"string\": \"foo\"}");
- sw.push_back("Skan\004bool\045\0010\005bool2\045\0011\004real\047\0042\05634\006string\050\003foo");
- sv.push_back("{\"list\": [ 1, 2, 3, 4 ]}");
- sw.push_back("Skan\004list\043\014\046\0011\046\0012\046\0013\046\0014");
-
- // some big ones
-
- bigstring << "{\"bigstring\": \"";
- bigwire << "Skan\011bigstring\030\001\001";
- for (size_t i = 0; i < 257; i++) {
- bigstring << "x";
- bigwire << "x";
- }
- bigstring << "\"}";
- sv.push_back(bigstring.str());
- sw.push_back(bigwire.str());
-
-
- bigstring2 << "{\"bigstring2\": \"";
- bigwire2 << "Skan\012bigstring2\010";
- bigwire2 << '\000' << '\001' << '\000' << '\001';
- for (size_t i = 0; i < 65537; i++) {
- bigstring2 << "x";
- bigwire2 << "x";
- }
- bigstring2 << "\"}";
- sv.push_back(bigstring2.str());
- sw.push_back(bigwire2.str());
-
-
- BOOST_FOREACH(std::string s, sv) {
- // also test << operator, which uses Element::str()
- el = Element::createFromString(s);
- EXPECT_EQ(s, el->str());
- wire = el->toWire();
- /*
- std::cout << "Encoded wire format:" << std::endl;
- my_print(wire);
- std::cout << "Expecting:" << std::endl;
- my_print(sw.at(0));
- */
- EXPECT_EQ(sw.at(0), wire);
- sw.erase(sw.begin());
- decoded_el = Element::fromWire(wire);
- EXPECT_EQ(s, decoded_el->str());
- }
-
- //EXPECT_THROW(Element::fromWire("Skan\004name\050\003foo"), DecodeError);
- EXPECT_THROW(Element::fromWire("Skan\004name\050"), DecodeError);
- EXPECT_THROW(Element::fromWire("Skan\004na"), DecodeError);
- EXPECT_THROW(Element::fromWire("Skan\004name\050\003fo"), DecodeError);
- EXPECT_NO_THROW(Element::fromWire("Skan\004name\041\003foo"));
- EXPECT_THROW(Element::fromWire("Skan\004name\041\003fo"), DecodeError);
- EXPECT_NO_THROW(Element::fromWire("Skan\004name\044\001a"));
- EXPECT_THROW(Element::fromWire("Skab\004name\050\003foo"), DecodeError);
-
- //EXPECT_EQ("\047\0031.2", Element::create(1.2)->toWire(0));
- EXPECT_EQ("\046\0011", Element::createFromString("[ 1 ]")->toWire(1));
-
- std::string ddef = "{\"data_specification\": {\"config_data\": [ {\"item_default\": \"Hello, world!\", \"item_name\": \"default_name\", \"item_optional\": False, \"item_type\": \"string\"}, {\"item_default\": [ ], \"item_name\": \"zone_list\", \"item_optional\": False, \"item_type\": \"list\", \"list_item_spec\": {\"item_name\": \"zone_name\", \"item_optional\": True, \"item_type\": \"string\"}} ], \"module_name\": \"Auth\"}}";
- //std::string ddef = "{\"aaa\": 123, \"test\": [ ], \"zzz\": 123}";
- ElementPtr ddef_el = Element::createFromString(ddef);
- std::string ddef_wire = ddef_el->toWire();
- ElementPtr ddef_el2 = Element::fromWire(ddef_wire);
- std::string ddef2 = ddef_el2->str();
- EXPECT_EQ(ddef, ddef2);
-}
-
-ElementPtr efs(const std::string& str) {
- return Element::createFromString(str);
+ // Wire format is now plain JSON.
+ ElementPtr el;
+ EXPECT_EQ("1", Element::create(1)->toWire());
+ EXPECT_EQ("1.1", Element::create(1.1)->toWire());
+ EXPECT_EQ("true", Element::create(true)->toWire());
+ EXPECT_EQ("false", Element::create(false)->toWire());
+ EXPECT_EQ("null", Element::create()->toWire());
+ EXPECT_EQ("\"a string\"", Element::create("a string")->toWire());
+ EXPECT_EQ("[ \"a\", \"list\" ]", Element::fromJSON("[ \"a\", \"list\" ]")->toWire());
+ EXPECT_EQ("{ \"a\": \"map\" }", Element::fromJSON("{ \"a\": \"map\" }")->toWire());
+
+ EXPECT_EQ("1", Element::fromWire("1")->str());
+
+ std::stringstream ss;
+ ss << "1";
+ EXPECT_EQ("1", Element::fromWire(ss, 1)->str());
+
+ // Some malformed JSON input
+ EXPECT_THROW(Element::fromJSON("{\":"), isc::data::JSONError);
+ EXPECT_THROW(Element::fromJSON("]"), isc::data::JSONError);
+ EXPECT_THROW(Element::fromJSON("[ 1, 2, }"), isc::data::JSONError);
+}
+
+static ElementPtr
+efs(const std::string& str) {
+ return Element::fromJSON(str);
}
TEST(Element, equals) {
// why does EXPECT_EQ not work?
- EXPECT_TRUE(efs("1") == efs("1"));
- EXPECT_FALSE(efs("1") == efs("2"));
- EXPECT_FALSE(efs("1") == efs("\"1\""));
- EXPECT_FALSE(efs("1") == efs("[]"));
- EXPECT_FALSE(efs("1") == efs("True"));
- EXPECT_FALSE(efs("1") == efs("{}"));
-
- EXPECT_TRUE(efs("1.1") == efs("1.1"));
- EXPECT_FALSE(efs("1.0") == efs("1"));
- EXPECT_FALSE(efs("1.1") == efs("\"1\""));
- EXPECT_FALSE(efs("1.1") == efs("[]"));
- EXPECT_FALSE(efs("1.1") == efs("True"));
- EXPECT_FALSE(efs("1.1") == efs("{}"));
-
- EXPECT_TRUE(efs("True") == efs("True"));
- EXPECT_FALSE(efs("True") == efs("False"));
- EXPECT_FALSE(efs("True") == efs("1"));
- EXPECT_FALSE(efs("True") == efs("\"1\""));
- EXPECT_FALSE(efs("True") == efs("[]"));
- EXPECT_FALSE(efs("True") == efs("{}"));
-
- EXPECT_TRUE(efs("\"foo\"") == efs("\"foo\""));
- EXPECT_FALSE(efs("\"foo\"") == efs("\"bar\""));
- EXPECT_FALSE(efs("\"foo\"") == efs("1"));
- EXPECT_FALSE(efs("\"foo\"") == efs("\"1\""));
- EXPECT_FALSE(efs("\"foo\"") == efs("True"));
- EXPECT_FALSE(efs("\"foo\"") == efs("[]"));
- EXPECT_FALSE(efs("\"foo\"") == efs("{}"));
-
- EXPECT_TRUE(efs("[]") == efs("[]"));
- EXPECT_TRUE(efs("[ 1, 2, 3 ]") == efs("[ 1, 2, 3 ]"));
- EXPECT_TRUE(efs("[ \"a\", [ True, 1], 2.2 ]") == efs("[ \"a\", [ True, 1], 2.2 ]"));
- EXPECT_FALSE(efs("[ \"a\", [ True, 1], 2.2 ]") == efs("[ \"a\", [ True, 2], 2.2 ]"));
- EXPECT_FALSE(efs("[]") == efs("[1]"));
- EXPECT_FALSE(efs("[]") == efs("1"));
- EXPECT_FALSE(efs("[]") == efs("\"1\""));
- EXPECT_FALSE(efs("[]") == efs("{}"));
-
- EXPECT_TRUE(efs("{}") == efs("{}"));
- EXPECT_TRUE(efs("{ \"foo\": \"bar\" }") == efs("{ \"foo\": \"bar\" }"));
- EXPECT_TRUE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
- EXPECT_FALSE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
- EXPECT_FALSE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
- EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("1"));
- EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("\"1\""));
- EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("[]"));
- EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("{}"));
+ EXPECT_EQ(efs("1"), efs("1"));
+ EXPECT_NE(efs("1"), efs("2"));
+ EXPECT_NE(efs("1"), efs("\"1\""));
+ EXPECT_NE(efs("1"), efs("[]"));
+ EXPECT_NE(efs("1"), efs("True"));
+ EXPECT_NE(efs("1"), efs("{}"));
+
+ EXPECT_EQ(efs("1.1"), efs("1.1"));
+ EXPECT_NE(efs("1.0"), efs("1"));
+ EXPECT_NE(efs("1.1"), efs("\"1\""));
+ EXPECT_NE(efs("1.1"), efs("[]"));
+ EXPECT_NE(efs("1.1"), efs("True"));
+ EXPECT_NE(efs("1.1"), efs("{}"));
+
+ EXPECT_EQ(efs("True"), efs("True"));
+ EXPECT_NE(efs("True"), efs("False"));
+ EXPECT_NE(efs("True"), efs("1"));
+ EXPECT_NE(efs("True"), efs("\"1\""));
+ EXPECT_NE(efs("True"), efs("[]"));
+ EXPECT_NE(efs("True"), efs("{}"));
+
+ EXPECT_EQ(efs("\"foo\""), efs("\"foo\""));
+ EXPECT_NE(efs("\"foo\""), efs("\"bar\""));
+ EXPECT_NE(efs("\"foo\""), efs("1"));
+ EXPECT_NE(efs("\"foo\""), efs("\"1\""));
+ EXPECT_NE(efs("\"foo\""), efs("True"));
+ EXPECT_NE(efs("\"foo\""), efs("[]"));
+ EXPECT_NE(efs("\"foo\""), efs("{}"));
+
+ EXPECT_EQ(efs("[]"), efs("[]"));
+ EXPECT_EQ(efs("[ 1, 2, 3 ]"), efs("[ 1, 2, 3 ]"));
+ EXPECT_EQ(efs("[ \"a\", [ True, 1], 2.2 ]"), efs("[ \"a\", [ True, 1], 2.2 ]"));
+ EXPECT_NE(efs("[ \"a\", [ True, 1], 2.2 ]"), efs("[ \"a\", [ True, 2], 2.2 ]"));
+ EXPECT_NE(efs("[]"), efs("[1]"));
+ EXPECT_NE(efs("[]"), efs("1"));
+ EXPECT_NE(efs("[]"), efs("\"1\""));
+ EXPECT_NE(efs("[]"), efs("{}"));
+
+ EXPECT_EQ(efs("{}"), efs("{}"));
+ EXPECT_EQ(efs("{ \"foo\": \"bar\" }"), efs("{ \"foo\": \"bar\" }"));
+ EXPECT_EQ(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
+ EXPECT_NE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
+ EXPECT_NE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"), efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
+ EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("1"));
+ EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("\"1\""));
+ EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("[]"));
+ EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("{}"));
+ EXPECT_NE(efs("{ \"foo\": \"bar\" }"), efs("{ \"something\": \"different\" }"));
+
+ EXPECT_EQ(efs("null"), Element::create());
}
TEST(Element, removeIdentical) {
- ElementPtr a = Element::createFromString("{}");
- ElementPtr b = Element::createFromString("{}");
- ElementPtr c = Element::createFromString("{}");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": 1 }");
- b = Element::createFromString("{ \"a\": 1 }");
- c = Element::createFromString("{}");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
- b = Element::createFromString("{}");
- c = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
- b = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
- c = Element::createFromString("{}");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
- b = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 3 ] }");
- c = Element::createFromString("{ \"b\": [ 1, 2 ] }");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
- b = Element::createFromString("{}");
- c = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
- b = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
- c = Element::createFromString("{}");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
- b = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
- c = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
- removeIdentical(a, b);
- EXPECT_TRUE(a == c);
+ ElementPtr a = Element::createMap();
+ ElementPtr b = Element::createMap();
+ ElementPtr c = Element::createMap();
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": 1 }");
+ b = Element::fromJSON("{ \"a\": 1 }");
+ c = Element::createMap();
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+ b = Element::createMap();
+ c = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+ b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+ c = Element::createMap();
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 2 ] }");
+ b = Element::fromJSON("{ \"a\": 1, \"b\": [ 1, 3 ] }");
+ c = Element::fromJSON("{ \"b\": [ 1, 2 ] }");
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ b = Element::createMap();
+ c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ b = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ c = Element::createMap();
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
+ c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ removeIdentical(a, b);
+ EXPECT_EQ(a, c);
+
+ EXPECT_THROW(removeIdentical(Element::create(1), Element::create(2)), TypeError);
}
TEST(Element, merge)
{
- ElementPtr a = Element::createFromString("{}");
- ElementPtr b = Element::createFromString("{}");
- ElementPtr c = Element::createFromString("{}");
- merge(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("1");
- b = Element::createFromString("{}");
+ ElementPtr a = Element::createMap();
+ ElementPtr b = Element::createMap();
+ ElementPtr c = Element::createMap();
+ merge(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("1");
+ b = Element::createMap();
EXPECT_THROW(merge(a, b), TypeError);
- a = Element::createFromString("{}");
- b = Element::createFromString("{ \"a\": 1 }");
- c = Element::createFromString("{ \"a\": 1 }");
- merge(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": 1 }");
- b = Element::createFromString("{ \"a\": 2 }");
- c = Element::createFromString("{ \"a\": 2 }");
- merge(a, b);
- EXPECT_TRUE(a == c);
-
- a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
- b = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
- c = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
- merge(a, b);
- EXPECT_TRUE(a == c);
-
-}
+ a = Element::createMap();
+ b = Element::fromJSON("{ \"a\": 1 }");
+ c = Element::fromJSON("{ \"a\": 1 }");
+ merge(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::createMap();
+ b = Element::fromJSON("{ \"a\": 1 }");
+ c = Element::fromJSON("{ \"a\": 1 }");
+ merge(b, a);
+ EXPECT_EQ(b, c);
+
+ a = Element::fromJSON("{ \"a\": 1 }");
+ b = Element::fromJSON("{ \"a\": 2 }");
+ c = Element::fromJSON("{ \"a\": 2 }");
+ merge(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": 1 }");
+ b = Element::fromJSON("{ \"a\": 2 }");
+ c = Element::fromJSON("{ \"a\": 1 }");
+ merge(b, a);
+ EXPECT_EQ(b, c);
+
+ a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
+ c = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
+ merge(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
+ c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ merge(b, a);
+ EXPECT_EQ(b, c);
+
+ a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ b = Element::fromJSON("{ \"a\": null }");
+ c = Element::fromJSON("{ }");
+ merge(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ b = Element::fromJSON("{ \"a\": null }");
+ c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
+ merge(b, a);
+ EXPECT_EQ(b, c);
+
+ // And some tests with multiple values
+ a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
+ b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
+ c = Element::fromJSON("{ \"a\": 1, \"c\": \"a string\" }");
+ merge(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
+ b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
+ c = Element::fromJSON("{ \"a\": 1, \"b\": true }");
+ merge(b, a);
+ EXPECT_EQ(b, c);
+
+ a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
+ b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
+ c = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
+ merge(a, b);
+ EXPECT_EQ(a, c);
+
+ a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
+ b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
+ c = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
+ merge(b, a);
+ EXPECT_EQ(b, c);
+
+}
Modified: trunk/src/lib/cc/session.cc
==============================================================================
--- trunk/src/lib/cc/session.cc (original)
+++ trunk/src/lib/cc/session.cc Wed Jun 30 19:05:31 2010
@@ -63,7 +63,7 @@
class SessionImpl {
public:
- SessionImpl() : sequence_(-1) { queue_ = Element::createFromString("[]"); }
+ SessionImpl() : sequence_(-1) { queue_ = Element::createList(); }
virtual ~SessionImpl() {}
virtual void establish(const char& socket_file) = 0;
virtual int getSocket() = 0;
@@ -73,7 +73,7 @@
virtual void readData(void* data, size_t datalen) = 0;
virtual void startRead(boost::function<void()> user_handler) = 0;
- int sequence_; // the next sequence number to use
+ long int sequence_; // the next sequence number to use
std::string lname_;
ElementPtr queue_;
};
@@ -321,7 +321,7 @@
// send a request for our local name, and wait for a response
//
ElementPtr get_lname_msg =
- Element::createFromString("{ \"type\": \"getlname\" }");
+ Element::fromJSON("{ \"type\": \"getlname\" }");
sendmsg(get_lname_msg);
ElementPtr routing, msg;
@@ -429,7 +429,7 @@
msg = l_msg;
return true;
} else {
- ElementPtr q_el = Element::createFromString("[]");
+ ElementPtr q_el = Element::createList();
q_el->add(l_env);
q_el->add(l_msg);
impl_->queue_->add(q_el);
@@ -440,7 +440,7 @@
void
Session::subscribe(std::string group, std::string instance) {
- ElementPtr env = Element::create(std::map<std::string, ElementPtr>());
+ ElementPtr env = Element::createMap();
env->set("type", Element::create("subscribe"));
env->set("group", Element::create(group));
@@ -451,7 +451,7 @@
void
Session::unsubscribe(std::string group, std::string instance) {
- ElementPtr env = Element::create(std::map<std::string, ElementPtr>());
+ ElementPtr env = Element::createMap();
env->set("type", Element::create("unsubscribe"));
env->set("group", Element::create(group));
@@ -464,8 +464,8 @@
Session::group_sendmsg(ElementPtr msg, std::string group,
std::string instance, std::string to)
{
- ElementPtr env = Element::create(std::map<std::string, ElementPtr>());
- int nseq = ++impl_->sequence_;
+ ElementPtr env = Element::createMap();
+ long int nseq = ++impl_->sequence_;
env->set("type", Element::create("send"));
env->set("from", Element::create(impl_->lname_));
@@ -488,8 +488,8 @@
int
Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
- ElementPtr env = Element::create(std::map<std::string, ElementPtr>());
- int nseq = ++impl_->sequence_;
+ ElementPtr env = Element::createMap();
+ long int nseq = ++impl_->sequence_;
env->set("type", Element::create("send"));
env->set("from", Element::create(impl_->lname_));
Modified: trunk/src/lib/config/ccsession.cc
==============================================================================
--- trunk/src/lib/config/ccsession.cc (original)
+++ trunk/src/lib/config/ccsession.cc Wed Jun 30 19:05:31 2010
@@ -47,7 +47,7 @@
using isc::data::Element;
using isc::data::ElementPtr;
-using isc::data::ParseError;
+using isc::data::JSONError;
namespace isc {
namespace config {
@@ -56,7 +56,7 @@
ElementPtr
createAnswer()
{
- ElementPtr answer = Element::createFromString("{\"result\": [] }");
+ ElementPtr answer = Element::fromJSON("{\"result\": [] }");
ElementPtr answer_content = answer->get("result");
answer_content->add(Element::create(0));
return answer;
@@ -68,7 +68,7 @@
if (rcode != 0 && (!arg || arg->getType() != Element::string)) {
isc_throw(CCSessionError, "Bad or no argument for rcode != 0");
}
- ElementPtr answer = Element::createFromString("{\"result\": [] }");
+ ElementPtr answer = Element::fromJSON("{\"result\": [] }");
ElementPtr answer_content = answer->get("result");
answer_content->add(Element::create(rcode));
answer_content->add(arg);
@@ -78,7 +78,7 @@
ElementPtr
createAnswer(const int rcode, const std::string& arg)
{
- ElementPtr answer = Element::createFromString("{\"result\": [] }");
+ ElementPtr answer = Element::fromJSON("{\"result\": [] }");
ElementPtr answer_content = answer->get("result");
answer_content->add(Element::create(rcode));
answer_content->add(Element::create(arg));
@@ -125,8 +125,8 @@
ElementPtr
createCommand(const std::string& command, ElementPtr arg)
{
- ElementPtr cmd = Element::createFromString("{}");
- ElementPtr cmd_parts = Element::createFromString("[]");
+ ElementPtr cmd = Element::createMap();
+ ElementPtr cmd_parts = Element::createList();
cmd_parts->add(Element::create(command));
if (arg) {
cmd_parts->add(arg);
@@ -175,7 +175,7 @@
try {
module_spec = moduleSpecFromFile(file, true);
- } catch (ParseError pe) {
+ } catch (JSONError pe) {
cout << "Error parsing module specification file: " << pe.what() << endl;
exit(1);
} catch (ModuleSpecError dde) {
@@ -252,10 +252,10 @@
std::cerr << "[" << module_name_ << "] Error in specification: " << answer << std::endl;
}
- setLocalConfig(Element::createFromString("{}"));
+ setLocalConfig(Element::fromJSON("{}"));
// get any stored configuration from the manager
if (config_handler_) {
- ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
+ ElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
seq = session_.group_sendmsg(cmd, "ConfigManager");
session_.group_recvmsg(env, answer, false, seq);
ElementPtr new_config = parseAnswer(rcode, answer);
@@ -274,7 +274,7 @@
ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
{
ElementPtr answer;
- ElementPtr errors = Element::createFromString("[]");
+ ElementPtr errors = Element::createList();
if (!config_handler_) {
answer = createAnswer(1, module_name_ + " does not have a config handler");
} else if (!module_specification_.validate_config(new_config, false, errors)) {
@@ -363,7 +363,7 @@
session_.subscribe(module_name);
// Get the current configuration values for that module
- ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
+ ElementPtr cmd = Element::fromJSON("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
ElementPtr env, answer;
int rcode;
Modified: trunk/src/lib/config/config_data.cc
==============================================================================
--- trunk/src/lib/config/config_data.cc (original)
+++ trunk/src/lib/config/config_data.cc Wed Jun 30 19:05:31 2010
@@ -26,6 +26,16 @@
namespace isc {
namespace config {
+//
+// Return a part of a specification, as identified by the
+// '/'-separated identifier.
+// If it cannot be found, a DataNotFound error is thrown.
+//
+// Recursively goes through the Element. If it is a List,
+// we search it contents to have 'items' (i.e. contain item_name)
+// If it is a map, we search through the list contained in its
+// 'map_item_spec' value. This code assumes the data has been
+// validated and conforms to the specification.
static ElementPtr
find_spec_part(ElementPtr spec, const std::string& identifier)
{
@@ -97,6 +107,11 @@
return spec_part;
}
+//
+// Adds the names of the items in the given specification part.
+// If recurse is true, maps will also have their children added.
+// Result must be a ListElement
+//
static void
spec_name_list(ElementPtr result, ElementPtr spec_part, std::string prefix, bool recurse = false)
{
@@ -129,6 +144,8 @@
ElementPtr
ConfigData::getValue(const std::string& identifier)
{
+ // 'fake' is set, but dropped by this function and
+ // serves no further purpose.
bool fake;
return getValue(fake, identifier);
}
@@ -158,7 +175,7 @@
ElementPtr
ConfigData::getItemList(const std::string& identifier, bool recurse)
{
- ElementPtr result = Element::createFromString("[]");
+ ElementPtr result = Element::createList();
ElementPtr spec_part = getModuleSpec().getConfigSpec();
if (identifier != "" && identifier != "/") {
spec_part = find_spec_part(spec_part, identifier);
@@ -172,7 +189,7 @@
ElementPtr
ConfigData::getFullConfig()
{
- ElementPtr result = Element::createFromString("{}");
+ ElementPtr result = Element::createMap();
ElementPtr items = getItemList("", true);
BOOST_FOREACH(ElementPtr item, items->listValue()) {
result->set(item->stringValue(), getValue(item->stringValue()));
Modified: trunk/src/lib/config/config_data.h
==============================================================================
--- trunk/src/lib/config/config_data.h (original)
+++ trunk/src/lib/config/config_data.h Wed Jun 30 19:05:31 2010
@@ -39,12 +39,12 @@
public:
/// Constructs a ConfigData option with no specification and an
/// empty configuration.
- ConfigData() { _config = Element::createFromString("{}"); };
+ ConfigData() { _config = Element::createMap(); };
/// Constructs a ConfigData option with the given specification
/// and an empty configuration.
/// \param module_spec A ModuleSpec for the relevant module
- ConfigData(const ModuleSpec& module_spec) : _module_spec(module_spec) { _config = Element::createFromString("{}"); }
+ ConfigData(const ModuleSpec& module_spec) : _module_spec(module_spec) { _config = Element::createMap(); }
virtual ~ConfigData() {};
Modified: trunk/src/lib/config/module_spec.cc
==============================================================================
--- trunk/src/lib/config/module_spec.cc (original)
+++ trunk/src/lib/config/module_spec.cc Wed Jun 30 19:05:31 2010
@@ -31,49 +31,6 @@
// static functions
//
-// todo: is there a direct way to get a std::string from an enum label?
-static std::string
-getType_string(Element::types type)
-{
- switch(type) {
- case Element::integer:
- return std::string("integer");
- case Element::real:
- return std::string("real");
- case Element::boolean:
- return std::string("boolean");
- case Element::string:
- return std::string("string");
- case Element::list:
- return std::string("list");
- case Element::map:
- return std::string("map");
- default:
- return std::string("unknown");
- }
-}
-
-static Element::types
-getType_value(const std::string& type_name) {
- if (type_name == "integer") {
- return Element::integer;
- } else if (type_name == "real") {
- return Element::real;
- } else if (type_name == "boolean") {
- return Element::boolean;
- } else if (type_name == "string") {
- return Element::string;
- } else if (type_name == "list") {
- return Element::list;
- } else if (type_name == "map") {
- return Element::map;
- } else if (type_name == "any") {
- return Element::any;
- } else {
- throw ModuleSpecError(type_name + " is not a valid type name");
- }
-}
-
static void
check_leaf_item(const ElementPtr& spec, const std::string& name, Element::types type, bool mandatory)
{
@@ -81,7 +38,7 @@
if (spec->get(name)->getType() == type) {
return;
} else {
- throw ModuleSpecError(name + " not of type " + getType_string(type));
+ throw ModuleSpecError(name + " not of type " + Element::typeToName(type));
}
} else if (mandatory) {
// todo: want parent item name, and perhaps some info about location
@@ -99,17 +56,17 @@
check_leaf_item(spec, "item_type", Element::string, true);
check_leaf_item(spec, "item_optional", Element::boolean, true);
check_leaf_item(spec, "item_default",
- getType_value(spec->get("item_type")->stringValue()),
+ Element::nameToType(spec->get("item_type")->stringValue()),
!spec->get("item_optional")->boolValue()
);
// if list, check the list specification
- if (getType_value(spec->get("item_type")->stringValue()) == Element::list) {
+ if (Element::nameToType(spec->get("item_type")->stringValue()) == Element::list) {
check_leaf_item(spec, "list_item_spec", Element::map, true);
check_config_item(spec->get("list_item_spec"));
}
// todo: add stuff for type map
- if (getType_value(spec->get("item_type")->stringValue()) == Element::map) {
+ if (Element::nameToType(spec->get("item_type")->stringValue()) == Element::map) {
check_leaf_item(spec, "map_item_spec", Element::list, true);
check_config_item_list(spec->get("map_item_spec"));
}
@@ -161,7 +118,11 @@
static void
check_module_specification(const ElementPtr& def)
{
- check_data_specification(def);
+ try {
+ check_data_specification(def);
+ } catch (TypeError te) {
+ throw ModuleSpecError(te.what());
+ }
}
//
@@ -231,7 +192,7 @@
ModuleSpec
moduleSpecFromFile(const std::string& file_name, const bool check)
- throw(ParseError, ModuleSpecError)
+ throw(JSONError, ModuleSpecError)
{
std::ifstream file;
@@ -242,7 +203,7 @@
throw ModuleSpecError(errs.str());
}
- ElementPtr module_spec_element = Element::createFromString(file, file_name);
+ ElementPtr module_spec_element = Element::fromJSON(file, file_name);
if (module_spec_element->contains("module_spec")) {
return ModuleSpec(module_spec_element->get("module_spec"), check);
} else {
@@ -252,8 +213,8 @@
ModuleSpec
moduleSpecFromFile(std::ifstream& in, const bool check)
- throw(ParseError, ModuleSpecError) {
- ElementPtr module_spec_element = Element::createFromString(in);
+ throw(JSONError, ModuleSpecError) {
+ ElementPtr module_spec_element = Element::fromJSON(in);
if (module_spec_element->contains("module_spec")) {
return ModuleSpec(module_spec_element->get("module_spec"), check);
} else {
Modified: trunk/src/lib/config/module_spec.h
==============================================================================
--- trunk/src/lib/config/module_spec.h (original)
+++ trunk/src/lib/config/module_spec.h Wed Jun 30 19:05:31 2010
@@ -110,7 +110,7 @@
/// is checked to be of the correct form
ModuleSpec
moduleSpecFromFile(const std::string& file_name, const bool check = true)
- throw(ParseError, ModuleSpecError);
+ throw(JSONError, ModuleSpecError);
/// Creates a \c ModuleSpec instance from the given input
/// stream that contains the contents of a .spec file.
@@ -122,7 +122,7 @@
/// to be of the correct form
ModuleSpec
moduleSpecFromFile(std::ifstream& in, const bool check = true)
- throw(ParseError, ModuleSpecError);
+ throw(JSONError, ModuleSpecError);
} }
#endif // _DATA_DEF_H
Modified: trunk/src/lib/config/tests/ccsession_unittests.cc
==============================================================================
--- trunk/src/lib/config/tests/ccsession_unittests.cc (original)
+++ trunk/src/lib/config/tests/ccsession_unittests.cc Wed Jun 30 19:05:31 2010
@@ -37,7 +37,7 @@
static ElementPtr
el(const std::string& str)
{
- return Element::createFromString(str);
+ return Element::fromJSON(str);
}
// upon creation of a ModuleCCSession, the class
@@ -66,16 +66,16 @@
{
ElementPtr answer;
answer = createAnswer();
- EXPECT_EQ("{\"result\": [ 0 ]}", answer->str());
+ EXPECT_EQ("{ \"result\": [ 0 ] }", answer->str());
answer = createAnswer(1, "error");
- EXPECT_EQ("{\"result\": [ 1, \"error\" ]}", answer->str());
+ EXPECT_EQ("{ \"result\": [ 1, \"error\" ] }", answer->str());
EXPECT_THROW(createAnswer(1, ElementPtr()), CCSessionError);
EXPECT_THROW(createAnswer(1, Element::create(1)), CCSessionError);
ElementPtr arg = el("[ \"just\", \"some\", \"data\" ]");
answer = createAnswer(0, arg);
- EXPECT_EQ("{\"result\": [ 0, [ \"just\", \"some\", \"data\" ] ]}", answer->str());
+ EXPECT_EQ("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }", answer->str());
}
TEST(CCSession, parseAnswer)
@@ -87,24 +87,24 @@
EXPECT_THROW(parseAnswer(rcode, ElementPtr()), CCSessionError);
EXPECT_THROW(parseAnswer(rcode, el("1")), CCSessionError);
EXPECT_THROW(parseAnswer(rcode, el("[]")), CCSessionError);
- EXPECT_THROW(parseAnswer(rcode, el("{}")), CCSessionError);
+ EXPECT_THROW(parseAnswer(rcode, el("{ }")), CCSessionError);
EXPECT_THROW(parseAnswer(rcode, el("{ \"something\": 1 }")), CCSessionError);
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": 0 }")), CCSessionError);
EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": 1 }")), CCSessionError);
- EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1 ]}")), CCSessionError);
- EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1, 1 ]}")), CCSessionError);
-
- answer = el("{\"result\": [ 0 ]}");
+ EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1 ] }")), CCSessionError);
+ EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1, 1 ] }")), CCSessionError);
+
+ answer = el("{ \"result\": [ 0 ] }");
arg = parseAnswer(rcode, answer);
EXPECT_EQ(0, rcode);
EXPECT_TRUE(isNull(arg));
- answer = el("{\"result\": [ 1, \"error\"]}");
+ answer = el("{ \"result\": [ 1, \"error\"] }");
arg = parseAnswer(rcode, answer);
EXPECT_EQ(1, rcode);
EXPECT_EQ("error", arg->stringValue());
- answer = el("{\"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }");
+ answer = el("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }");
arg = parseAnswer(rcode, answer);
EXPECT_EQ(0, rcode);
EXPECT_EQ("[ \"just\", \"some\", \"data\" ]", arg->str());
@@ -116,19 +116,19 @@
ElementPtr arg;
command = createCommand("my_command");
- ASSERT_EQ("{\"command\": [ \"my_command\" ]}", command->str());
+ ASSERT_EQ("{ \"command\": [ \"my_command\" ] }", command->str());
arg = el("1");
command = createCommand("my_command", arg);
- ASSERT_EQ("{\"command\": [ \"my_command\", 1 ]}", command->str());
+ ASSERT_EQ("{ \"command\": [ \"my_command\", 1 ] }", command->str());
arg = el("[ \"a\", \"b\" ]");
command = createCommand("my_cmd", arg);
- ASSERT_EQ("{\"command\": [ \"my_cmd\", [ \"a\", \"b\" ] ]}", command->str());
+ ASSERT_EQ("{ \"command\": [ \"my_cmd\", [ \"a\", \"b\" ] ] }", command->str());
arg = el("{ \"a\": \"map\" }");
command = createCommand("foo", arg);
- ASSERT_EQ("{\"command\": [ \"foo\", {\"a\": \"map\"} ]}", command->str());
+ ASSERT_EQ("{ \"command\": [ \"foo\", { \"a\": \"map\" } ] }", command->str());
}
TEST(CCSession, parseCommand)
@@ -139,21 +139,21 @@
// should throw
EXPECT_THROW(parseCommand(arg, ElementPtr()), CCSessionError);
EXPECT_THROW(parseCommand(arg, el("1")), CCSessionError);
- EXPECT_THROW(parseCommand(arg, el("{}")), CCSessionError);
- EXPECT_THROW(parseCommand(arg, el("{\"not a command\": 1 }")), CCSessionError);
- EXPECT_THROW(parseCommand(arg, el("{\"command\": 1 }")), CCSessionError);
- EXPECT_THROW(parseCommand(arg, el("{\"command\": [] }")), CCSessionError);
- EXPECT_THROW(parseCommand(arg, el("{\"command\": [ 1 ] }")), CCSessionError);
-
- cmd = parseCommand(arg, el("{\"command\": [ \"my_command\" ] }"));
+ EXPECT_THROW(parseCommand(arg, el("{ }")), CCSessionError);
+ EXPECT_THROW(parseCommand(arg, el("{ \"not a command\": 1 }")), CCSessionError);
+ EXPECT_THROW(parseCommand(arg, el("{ \"command\": 1 }")), CCSessionError);
+ EXPECT_THROW(parseCommand(arg, el("{ \"command\": [] }")), CCSessionError);
+ EXPECT_THROW(parseCommand(arg, el("{ \"command\": [ 1 ] }")), CCSessionError);
+
+ cmd = parseCommand(arg, el("{ \"command\": [ \"my_command\" ] }"));
EXPECT_EQ("my_command", cmd);
EXPECT_TRUE(isNull(arg));
- cmd = parseCommand(arg, el("{\"command\": [ \"my_command\", 1 ] }"));
+ cmd = parseCommand(arg, el("{ \"command\": [ \"my_command\", 1 ] }"));
EXPECT_EQ("my_command", cmd);
EXPECT_EQ("1", arg->str());
- parseCommand(arg, el("{\"command\": [ \"my_command\", [ \"some\", \"argument\", \"list\" ] ] }"));
+ parseCommand(arg, el("{ \"command\": [ \"my_command\", [ \"some\", \"argument\", \"list\" ] ] }"));
EXPECT_EQ("my_command", cmd);
EXPECT_EQ("[ \"some\", \"argument\", \"list\" ]", arg->str());
@@ -170,7 +170,7 @@
ElementPtr msg;
std::string group, to;
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"command\": [ \"module_spec\", {\"module_name\": \"Spec1\"} ]}", msg->str());
+ EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"module_name\": \"Spec1\" } ] }", msg->str());
EXPECT_EQ("ConfigManager", group);
EXPECT_EQ("*", to);
EXPECT_EQ(0, msg_queue->size());
@@ -188,7 +188,7 @@
ElementPtr msg;
std::string group, to;
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"command\": [ \"module_spec\", {\"commands\": [ {\"command_args\": [ {\"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": False, \"item_type\": \"string\"} ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\"}, {\"command_args\": [ ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\"} ], \"config_data\": [ {\"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": False, \"item_type\": \"integer\"}, {\"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": False, \"item_type\": \"real\"}, {\"item_default\": True, \"item_name\": \"item3\", \"item_optional\": False, \"item_type\": \"boolean\"}, {\"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": False, \"item_type\": \"string\"}, {\"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": False, \"item_type\": \"list\", \"list_item_spec\": {\"item_def
ault\": \"\", \"item_name\": \"list_element\", \"item_optional\": False, \"item_type\": \"string\"}}, {\"item_default\": {}, \"item_name\": \"item6\", \"item_optional\": False, \"item_type\": \"map\", \"map_item_spec\": [ {\"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": True, \"item_type\": \"string\"}, {\"item_name\": \"value2\", \"item_optional\": True, \"item_type\": \"integer\"} ]} ], \"module_name\": \"Spec2\"} ]}", msg->str());
+ EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"commands\": [ { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }, { \"command_args\": [ ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\" } ], \"config_data\": [ { \"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": false, \"item_type\": \"integer\" }, { \"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": false, \"item_type\": \"real\" }, { \"item_default\": true, \"item_name\": \"item3\", \"item_optional\": false, \"item_type\": \"boolean\" }, { \"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": false, \"item_type\": \"string\" }, { \"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": false, \"item_type\": \"list\", \"list_item_sp
ec\": { \"item_default\": \"\", \"item_name\": \"list_element\", \"item_optional\": false, \"item_type\": \"string\" } }, { \"item_default\": { }, \"item_name\": \"item6\", \"item_optional\": false, \"item_type\": \"map\", \"map_item_spec\": [ { \"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": true, \"item_type\": \"string\" }, { \"item_name\": \"value2\", \"item_optional\": true, \"item_type\": \"integer\" } ] } ], \"module_name\": \"Spec2\" } ] }", msg->str());
EXPECT_EQ("ConfigManager", group);
EXPECT_EQ("*", to);
EXPECT_EQ(0, msg_queue->size());
@@ -227,7 +227,7 @@
{
initFakeSession();
// client will ask for config
- initial_messages->add(createAnswer(0, el("{}")));
+ initial_messages->add(createAnswer(0, el("{ }")));
EXPECT_EQ(false, haveSubscription("Spec2", "*"));
ModuleCCSession mccs(ccspecfile("spec2.spec"), my_config_handler, my_command_handler);
@@ -237,12 +237,12 @@
ElementPtr msg;
std::string group, to;
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"command\": [ \"module_spec\", {\"commands\": [ {\"command_args\": [ {\"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": False, \"item_type\": \"string\"} ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\"}, {\"command_args\": [ ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\"} ], \"config_data\": [ {\"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": False, \"item_type\": \"integer\"}, {\"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": False, \"item_type\": \"real\"}, {\"item_default\": True, \"item_name\": \"item3\", \"item_optional\": False, \"item_type\": \"boolean\"}, {\"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": False, \"item_type\": \"string\"}, {\"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": False, \"item_type\": \"list\", \"list_item_spec\": {\"item_def
ault\": \"\", \"item_name\": \"list_element\", \"item_optional\": False, \"item_type\": \"string\"}}, {\"item_default\": {}, \"item_name\": \"item6\", \"item_optional\": False, \"item_type\": \"map\", \"map_item_spec\": [ {\"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": True, \"item_type\": \"string\"}, {\"item_name\": \"value2\", \"item_optional\": True, \"item_type\": \"integer\"} ]} ], \"module_name\": \"Spec2\"} ]}", msg->str());
+ EXPECT_EQ("{ \"command\": [ \"module_spec\", { \"commands\": [ { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }, { \"command_args\": [ ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\" } ], \"config_data\": [ { \"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": false, \"item_type\": \"integer\" }, { \"item_default\": 1.1, \"item_name\": \"item2\", \"item_optional\": false, \"item_type\": \"real\" }, { \"item_default\": true, \"item_name\": \"item3\", \"item_optional\": false, \"item_type\": \"boolean\" }, { \"item_default\": \"test\", \"item_name\": \"item4\", \"item_optional\": false, \"item_type\": \"string\" }, { \"item_default\": [ \"a\", \"b\" ], \"item_name\": \"item5\", \"item_optional\": false, \"item_type\": \"list\", \"list_item_sp
ec\": { \"item_default\": \"\", \"item_name\": \"list_element\", \"item_optional\": false, \"item_type\": \"string\" } }, { \"item_default\": { }, \"item_name\": \"item6\", \"item_optional\": false, \"item_type\": \"map\", \"map_item_spec\": [ { \"item_default\": \"default\", \"item_name\": \"value1\", \"item_optional\": true, \"item_type\": \"string\" }, { \"item_name\": \"value2\", \"item_optional\": true, \"item_type\": \"integer\" } ] } ], \"module_name\": \"Spec2\" } ] }", msg->str());
EXPECT_EQ("ConfigManager", group);
EXPECT_EQ("*", to);
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"command\": [ \"get_config\", {\"module_name\": \"Spec2\"} ]}", msg->str());
+ EXPECT_EQ("{ \"command\": [ \"get_config\", { \"module_name\": \"Spec2\" } ] }", msg->str());
EXPECT_EQ("ConfigManager", group);
EXPECT_EQ("*", to);
EXPECT_EQ(0, msg_queue->size());
@@ -253,7 +253,7 @@
{
initFakeSession();
// client will ask for config
- initial_messages->add(createAnswer(0, el("{}")));
+ initial_messages->add(createAnswer(0, el("{ }")));
EXPECT_EQ(false, haveSubscription("Spec2", "*"));
ModuleCCSession mccs(ccspecfile("spec2.spec"), my_config_handler, my_command_handler);
@@ -279,42 +279,42 @@
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 0 ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
EXPECT_EQ(0, result);
addMessage(el("{ \"command\": \"bad_command\" }"), "Spec2", "*");
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 1, \"Command part in command message missing, empty, or not a list\" ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 1, \"Command part in command message missing, empty, or not a list\" ] }", msg->str());
EXPECT_EQ(0, result);
addMessage(el("{ \"command\": [ \"bad_command\" ] }"), "Spec2", "*");
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 1, \"bad command\" ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 1, \"bad command\" ] }", msg->str());
EXPECT_EQ(0, result);
addMessage(el("{ \"command\": [ \"command_with_arg\", 1 ] }"), "Spec2", "*");
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 0, 2 ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 0, 2 ] }", msg->str());
EXPECT_EQ(0, result);
addMessage(el("{ \"command\": [ \"command_with_arg\" ] }"), "Spec2", "*");
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 1, \"arg missing\" ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 1, \"arg missing\" ] }", msg->str());
EXPECT_EQ(0, result);
addMessage(el("{ \"command\": [ \"command_with_arg\", \"asdf\" ] }"), "Spec2", "*");
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 1, \"arg bad type\" ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 1, \"arg bad type\" ] }", msg->str());
EXPECT_EQ(0, result);
mccs.setCommandHandler(NULL);
@@ -322,7 +322,7 @@
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 1, \"Command given but no command handler for module\" ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 1, \"Command given but no command handler for module\" ] }", msg->str());
EXPECT_EQ(0, result);
EXPECT_EQ(1, mccs.getValue("item1")->intValue());
@@ -330,7 +330,7 @@
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 0 ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 0 ] }", msg->str());
EXPECT_EQ(0, result);
EXPECT_EQ(2, mccs.getValue("item1")->intValue());
@@ -338,7 +338,7 @@
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 2, \"Error in config validation: Type mismatch\" ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 2, \"Error in config validation: Type mismatch\" ] }", msg->str());
EXPECT_EQ(0, result);
EXPECT_EQ(2, mccs.getValue("item1")->intValue());
@@ -346,7 +346,7 @@
result = mccs.checkCommand();
EXPECT_EQ(1, msg_queue->size());
msg = getFirstMessage(group, to);
- EXPECT_EQ("{\"result\": [ 6, \"I do not like the number 5\" ]}", msg->str());
+ EXPECT_EQ("{ \"result\": [ 6, \"I do not like the number 5\" ] }", msg->str());
EXPECT_EQ(0, result);
EXPECT_EQ(2, mccs.getValue("item1")->intValue());
@@ -364,7 +364,7 @@
// first simply connect, with no config values, and see we get
// the default
- initial_messages->add(createAnswer(0, el("{}")));
+ initial_messages->add(createAnswer(0, el("{ }")));
EXPECT_EQ(false, haveSubscription("Spec2", "*"));
module_name = mccs.addRemoteConfig(ccspecfile("spec2.spec"));
@@ -393,7 +393,7 @@
// remove, re-add, now with a *bad* config request answer
mccs.removeRemoteConfig(module_name);
- initial_messages->add(el("{}"));
+ initial_messages->add(el("{ }"));
EXPECT_THROW(mccs.addRemoteConfig(ccspecfile("spec2.spec")), CCSessionError);
initial_messages->add(createAnswer(1, "my_error"));
Modified: trunk/src/lib/config/tests/config_data_unittests.cc
==============================================================================
--- trunk/src/lib/config/tests/config_data_unittests.cc (original)
+++ trunk/src/lib/config/tests/config_data_unittests.cc Wed Jun 30 19:05:31 2010
@@ -62,9 +62,9 @@
EXPECT_EQ("b", cd.getValue(is_default, "value5")->get(1)->stringValue());
EXPECT_EQ("b", cd.getValue(is_default, "value5/")->get(1)->stringValue());
EXPECT_TRUE(is_default);
- EXPECT_EQ("{}", cd.getValue("value6")->str());
- EXPECT_EQ("{}", cd.getValue(is_default, "value6")->str());
- EXPECT_EQ("{}", cd.getValue(is_default, "value6/")->str());
+ EXPECT_EQ("{ }", cd.getValue("value6")->str());
+ EXPECT_EQ("{ }", cd.getValue(is_default, "value6")->str());
+ EXPECT_EQ("{ }", cd.getValue(is_default, "value6/")->str());
EXPECT_TRUE(is_default);
EXPECT_EQ("[ ]", cd.getValue("value8")->str());
@@ -87,34 +87,34 @@
ConfigData cd = ConfigData(spec2);
bool is_default;
- ElementPtr my_config = Element::createFromString("{\"item1\": 2}");
- ElementPtr my_config2 = Element::createFromString("{\"item6\": { \"value1\": \"a\" } }");
+ ElementPtr my_config = Element::fromJSON("{ \"item1\": 2 }");
+ ElementPtr my_config2 = Element::fromJSON("{ \"item6\": { \"value1\": \"a\" } }");
- EXPECT_EQ("{}", cd.getValue("item6")->str());
+ EXPECT_EQ("{ }", cd.getValue("item6")->str());
cd.setLocalConfig(my_config);
EXPECT_EQ(2, cd.getValue(is_default, "item1")->intValue());
EXPECT_FALSE(is_default);
- EXPECT_EQ("{}", cd.getValue("item6")->str());
+ EXPECT_EQ("{ }", cd.getValue("item6")->str());
EXPECT_EQ(1.1, cd.getValue(is_default, "item2")->doubleValue());
EXPECT_TRUE(is_default);
cd.setLocalConfig(my_config2);
- EXPECT_EQ("{\"value1\": \"a\"}", cd.getValue("item6")->str());
+ EXPECT_EQ("{ \"value1\": \"a\" }", cd.getValue("item6")->str());
}
TEST(ConfigData, getLocalConfig) {
ModuleSpec spec2 = moduleSpecFromFile(std::string(TEST_DATA_PATH) + "/spec2.spec");
ConfigData cd = ConfigData(spec2);
- EXPECT_EQ("{}", cd.getLocalConfig()->str());
+ EXPECT_EQ("{ }", cd.getLocalConfig()->str());
- ElementPtr my_config = Element::createFromString("{\"item1\": 2}");
+ ElementPtr my_config = Element::fromJSON("{ \"item1\": 2 }");
cd.setLocalConfig(my_config);
- EXPECT_EQ("{\"item1\": 2}", cd.getLocalConfig()->str());
+ EXPECT_EQ("{ \"item1\": 2 }", cd.getLocalConfig()->str());
- ElementPtr my_config2 = Element::createFromString("{\"item6\": { \"value1\": \"a\" } }");
+ ElementPtr my_config2 = Element::fromJSON("{ \"item6\": { \"value1\": \"a\" } }");
cd.setLocalConfig(my_config2);
- EXPECT_EQ("{\"item6\": {\"value1\": \"a\"}}", cd.getLocalConfig()->str());
+ EXPECT_EQ("{ \"item6\": { \"value1\": \"a\" } }", cd.getLocalConfig()->str());
}
TEST(ConfigData, getItemList) {
@@ -130,12 +130,12 @@
ModuleSpec spec2 = moduleSpecFromFile(std::string(TEST_DATA_PATH) + "/spec2.spec");
ConfigData cd = ConfigData(spec2);
- EXPECT_EQ("{\"item1\": 1, \"item2\": 1.1, \"item3\": True, \"item4\": \"test\", \"item5/\": [ \"a\", \"b\" ], \"item6/value1\": \"default\", \"item6/value2\": None}", cd.getFullConfig()->str());
- ElementPtr my_config = Element::createFromString("{\"item1\": 2}");
+ EXPECT_EQ("{ \"item1\": 1, \"item2\": 1.1, \"item3\": true, \"item4\": \"test\", \"item5/\": [ \"a\", \"b\" ], \"item6/value1\": \"default\", \"item6/value2\": None }", cd.getFullConfig()->str());
+ ElementPtr my_config = Element::fromJSON("{ \"item1\": 2 }");
cd.setLocalConfig(my_config);
- EXPECT_EQ("{\"item1\": 2, \"item2\": 1.1, \"item3\": True, \"item4\": \"test\", \"item5/\": [ \"a\", \"b\" ], \"item6/value1\": \"default\", \"item6/value2\": None}", cd.getFullConfig()->str());
- ElementPtr my_config2 = Element::createFromString("{\"item6\": { \"value1\": \"a\" } }");
+ EXPECT_EQ("{ \"item1\": 2, \"item2\": 1.1, \"item3\": true, \"item4\": \"test\", \"item5/\": [ \"a\", \"b\" ], \"item6/value1\": \"default\", \"item6/value2\": None }", cd.getFullConfig()->str());
+ ElementPtr my_config2 = Element::fromJSON("{ \"item6\": { \"value1\": \"a\" } }");
cd.setLocalConfig(my_config2);
- EXPECT_EQ("{\"item1\": 1, \"item2\": 1.1, \"item3\": True, \"item4\": \"test\", \"item5/\": [ \"a\", \"b\" ], \"item6/value1\": \"a\", \"item6/value2\": None}", cd.getFullConfig()->str());
+ EXPECT_EQ("{ \"item1\": 1, \"item2\": 1.1, \"item3\": true, \"item4\": \"test\", \"item5/\": [ \"a\", \"b\" ], \"item6/value1\": \"a\", \"item6/value2\": None }", cd.getFullConfig()->str());
}
Modified: trunk/src/lib/config/tests/fake_session.cc
==============================================================================
--- trunk/src/lib/config/tests/fake_session.cc (original)
+++ trunk/src/lib/config/tests/fake_session.cc Wed Jun 30 19:05:31 2010
@@ -92,12 +92,12 @@
void
addMessage(ElementPtr msg, const std::string& group, const std::string& to)
{
- ElementPtr m_el = Element::createFromString("[]");
+ ElementPtr m_el = Element::createList();
m_el->add(Element::create(group));
m_el->add(Element::create(to));
m_el->add(msg);
if (!msg_queue) {
- msg_queue = Element::createFromString("[]");
+ msg_queue = Element::createList();
}
msg_queue->add(m_el);
}
@@ -108,8 +108,8 @@
if (!subscriptions) {
return false;
}
- ElementPtr s1 = Element::createFromString("[]");
- ElementPtr s2 = Element::createFromString("[]");
+ ElementPtr s1 = Element::createList();
+ ElementPtr s2 = Element::createList();
s1->add(Element::create(group));
s1->add(Element::create(instance));
s2->add(Element::create(group));
@@ -206,7 +206,7 @@
BOOST_FOREACH(ElementPtr c_m, msg_queue->listValue()) {
ElementPtr to_remove = ElementPtr();
if (haveSubscription(c_m->get(0), c_m->get(1))) {
- env = Element::createFromString("{}");
+ env = Element::createMap();
env->set("group", c_m->get(0));
env->set("to", c_m->get(1));
msg = c_m->get(2);
@@ -226,11 +226,11 @@
void
Session::subscribe(std::string group, std::string instance) {
//cout << "[XX] client subscribes to " << group << " . " << instance << endl;
- ElementPtr s_el = Element::createFromString("[]");
+ ElementPtr s_el = Element::createList();
s_el->add(Element::create(group));
s_el->add(Element::create(instance));
if (!subscriptions) {
- subscriptions = Element::createFromString("[]");
+ subscriptions = Element::createList();
}
subscriptions->add(s_el);
}
@@ -238,7 +238,7 @@
void
Session::unsubscribe(std::string group, std::string instance) {
//cout << "[XX] client unsubscribes from " << group << " . " << instance << endl;
- ElementPtr s_el = Element::createFromString("[]");
+ ElementPtr s_el = Element::createList();
s_el->add(Element::create(group));
s_el->add(Element::create(instance));
if (!subscriptions) {
Modified: trunk/src/lib/config/tests/module_spec_unittests.cc
==============================================================================
--- trunk/src/lib/config/tests/module_spec_unittests.cc (original)
+++ trunk/src/lib/config/tests/module_spec_unittests.cc Wed Jun 30 19:05:31 2010
@@ -58,7 +58,7 @@
": No such file or directory");
dd = moduleSpecFromFile(specfile("spec2.spec"));
- EXPECT_EQ("[ {\"command_args\": [ {\"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": False, \"item_type\": \"string\"} ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\"}, {\"command_args\": [ ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\"} ]", dd.getCommandsSpec()->str());
+ EXPECT_EQ("[ { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }, { \"command_args\": [ ], \"command_description\": \"Shut down BIND 10\", \"command_name\": \"shutdown\" } ]", dd.getCommandsSpec()->str());
EXPECT_EQ("Spec2", dd.getModuleName());
EXPECT_EQ("", dd.getModuleDescription());
@@ -82,13 +82,13 @@
TEST(ModuleSpec, SpecfileItems) {
module_spec_error("spec3.spec",
- "item_name missing in {\"item_default\": 1, \"item_optional\": False, \"item_type\": \"integer\"}");
+ "item_name missing in { \"item_default\": 1, \"item_optional\": false, \"item_type\": \"integer\" }");
module_spec_error("spec4.spec",
- "item_type missing in {\"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": False}");
+ "item_type missing in { \"item_default\": 1, \"item_name\": \"item1\", \"item_optional\": false }");
module_spec_error("spec5.spec",
- "item_optional missing in {\"item_default\": 1, \"item_name\": \"item1\", \"item_type\": \"integer\"}");
+ "item_optional missing in { \"item_default\": 1, \"item_name\": \"item1\", \"item_type\": \"integer\" }");
module_spec_error("spec6.spec",
- "item_default missing in {\"item_name\": \"item1\", \"item_optional\": False, \"item_type\": \"integer\"}");
+ "item_default missing in { \"item_name\": \"item1\", \"item_optional\": false, \"item_type\": \"integer\" }");
module_spec_error("spec9.spec",
"item_default not of type integer");
module_spec_error("spec10.spec",
@@ -108,7 +108,7 @@
TEST(ModuleSpec, SpecfileConfigData)
{
module_spec_error("spec7.spec",
- "module_name missing in {}");
+ "module_name missing in { }");
module_spec_error("spec8.spec",
"No module_spec in specification");
module_spec_error("spec16.spec",
@@ -120,9 +120,9 @@
TEST(ModuleSpec, SpecfileCommands)
{
module_spec_error("spec17.spec",
- "command_name missing in {\"command_args\": [ {\"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": False, \"item_type\": \"string\"} ], \"command_description\": \"Print the given message to stdout\"}");
+ "command_name missing in { \"command_args\": [ { \"item_default\": \"\", \"item_name\": \"message\", \"item_optional\": false, \"item_type\": \"string\" } ], \"command_description\": \"Print the given message to stdout\" }");
module_spec_error("spec18.spec",
- "command_args missing in {\"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\"}");
+ "command_args missing in { \"command_description\": \"Print the given message to stdout\", \"command_name\": \"print_message\" }");
module_spec_error("spec19.spec",
"command_args not of type list");
module_spec_error("spec20.spec",
@@ -139,7 +139,7 @@
std::ifstream data_file;
data_file.open(specfile(data_file_name).c_str());
- ElementPtr data = Element::createFromString(data_file, data_file_name);
+ ElementPtr data = Element::fromJSON(data_file, data_file_name);
data_file.close();
return dd.validate_config(data);
@@ -151,7 +151,7 @@
std::ifstream data_file;
data_file.open(specfile(data_file_name).c_str());
- ElementPtr data = Element::createFromString(data_file, data_file_name);
+ ElementPtr data = Element::fromJSON(data_file, data_file_name);
data_file.close();
return dd.validate_config(data, true, errors);
@@ -169,7 +169,7 @@
EXPECT_TRUE(data_test(dd, "data22_7.data"));
EXPECT_FALSE(data_test(dd, "data22_8.data"));
- ElementPtr errors = Element::createFromString("[]");
+ ElementPtr errors = Element::createList();
EXPECT_FALSE(data_test_with_errors(dd, "data22_8.data", errors));
EXPECT_EQ("[ \"Type mismatch\" ]", errors->str());
}
Modified: trunk/src/lib/datasrc/tests/datasrc_unittest.cc
==============================================================================
--- trunk/src/lib/datasrc/tests/datasrc_unittest.cc (original)
+++ trunk/src/lib/datasrc/tests/datasrc_unittest.cc Wed Jun 30 19:05:31 2010
@@ -49,7 +49,7 @@
using namespace isc::data;
namespace {
-const ElementPtr SQLITE_DBFILE_EXAMPLE = Element::createFromString(
+const ElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
"{ \"database_file\": \"" TEST_DATA_DIR "/example.org.sqlite3\"}");
class DataSrcTest : public ::testing::Test {
Modified: trunk/src/lib/datasrc/tests/sqlite3_unittest.cc
==============================================================================
--- trunk/src/lib/datasrc/tests/sqlite3_unittest.cc (original)
+++ trunk/src/lib/datasrc/tests/sqlite3_unittest.cc Wed Jun 30 19:05:31 2010
@@ -43,22 +43,22 @@
using namespace isc::data;
namespace {
-ElementPtr SQLITE_DBFILE_EXAMPLE = Element::createFromString(
+ElementPtr SQLITE_DBFILE_EXAMPLE = Element::fromJSON(
"{ \"database_file\": \"" TEST_DATA_DIR "/test.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::createFromString(
+ElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::fromJSON(
"{ \"database_file\": \"" TEST_DATA_DIR "/example2.com.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_EXAMPLE_ROOT = Element::createFromString(
+ElementPtr SQLITE_DBFILE_EXAMPLE_ROOT = Element::fromJSON(
"{ \"database_file\": \"" TEST_DATA_DIR "/test-root.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_BROKENDB = Element::createFromString(
+ElementPtr SQLITE_DBFILE_BROKENDB = Element::fromJSON(
"{ \"database_file\": \"" TEST_DATA_DIR "/brokendb.sqlite3\"}");
-ElementPtr SQLITE_DBFILE_MEMORY = Element::createFromString(
+ElementPtr SQLITE_DBFILE_MEMORY = Element::fromJSON(
"{ \"database_file\": \":memory:\"}");
// The following file must be non existent and must be non"creatable";
// the sqlite3 library will try to create a new DB file if it doesn't exist,
// so to test a failure case the create operation should also fail.
// The "nodir", a non existent directory, is inserted for this purpose.
-ElementPtr SQLITE_DBFILE_NOTEXIST = Element::createFromString(
+ElementPtr SQLITE_DBFILE_NOTEXIST = Element::fromJSON(
"{ \"database_file\": \"" TEST_DATA_DIR "/nodir/notexist\"}");
const string sigdata_common(" 20100322084538 20100220084538 "
Modified: trunk/src/lib/python/isc/cc/message.py
==============================================================================
--- trunk/src/lib/python/isc/cc/message.py (original)
+++ trunk/src/lib/python/isc/cc/message.py Wed Jun 30 19:05:31 2010
@@ -13,224 +13,29 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Functions for reading and parsing cc messages
+# Currently these are only abstraction functions for JSON conversion.
+#
+
import sys
import struct
-class DecodeError(Exception): pass
-
-PROTOCOL_VERSION = 0x536b616e
-
-_ITEM_BLOB = 0x01
-_ITEM_HASH = 0x02
-_ITEM_LIST = 0x03
-_ITEM_NULL = 0x04
-_ITEM_BOOL = 0x05
-_ITEM_INT = 0x06
-_ITEM_REAL = 0x07
-_ITEM_UTF8 = 0x08
-_ITEM_MASK = 0x0f
-
-_ITEM_LENGTH_32 = 0x00
-_ITEM_LENGTH_16 = 0x10
-_ITEM_LENGTH_8 = 0x20
-_ITEM_LENGTH_MASK = 0x30
+import json
def to_wire(items):
- """Encode a dict into wire format.
- >>> wire_format = Message.to_wire({"a": "b"})
- """
- return struct.pack(">I", PROTOCOL_VERSION) + _encode_hash(items)
-
-def _encode_tag(tag):
- """Encode a single UTF-8 tag.
- ... wire_partial = Message._encode_tag('this')
- """
- binary = bytes(tag, 'utf-8')
- if len(binary) > 255:
- raise ArgumentError("tag is too long (max 255 encoded bytes)")
- return(struct.pack(">B", len(binary))) + binary
-
-def _encode_length_and_type(data, datatype):
- """Helper method to handle the length encoding in one place."""
- if data == None:
- return(struct.pack(">B", _ITEM_NULL))
- length = len(data)
- if length < 0x0000100:
- return(struct.pack(">B B", datatype | _ITEM_LENGTH_8, length) + data)
- elif length < 0x00010000:
- return(struct.pack(">B H", datatype | _ITEM_LENGTH_16, length) + data)
- else:
- return(struct.pack(">B I", datatype | _ITEM_LENGTH_32, length) + data)
-
-def _pack_utf8(item):
- """Pack a string (utf-8) and its type/length prefix."""
- return (_encode_length_and_type(bytes(item, 'utf-8'), _ITEM_UTF8))
-
-def _pack_blob(item):
- """Pack a blob (binary data) and its type/length prefix."""
- return (_encode_length_and_type(item, _ITEM_BLOB))
-
-def _pack_bool(item):
- """Pack a bool and its type/length prefix."""
- return (_encode_length_and_type(_encode_bool(item), _ITEM_BOOL))
-
-def _pack_int(item):
- """Pack an integer and its type/length prefix."""
- return (_encode_length_and_type(bytes(str(item), 'utf-8'), _ITEM_INT))
-
-def _pack_real(item):
- """Pack an integer and its type/length prefix."""
- return (_encode_length_and_type(bytes(str(item), 'utf-8'), _ITEM_REAL))
-
-def _pack_array(item):
- """Pack a list (array) and its type/length prefix."""
- return (_encode_length_and_type(_encode_array(item), _ITEM_LIST))
-
-def _pack_hash(item):
- """Pack a dict (hash) and its type/length prefix."""
- data = _encode_hash(item)
- return (_encode_length_and_type(data, _ITEM_HASH))
-
-def _pack_nil():
- """Encode a nil (NULL, None) item."""
- return _encode_length_and_type(None, None)
-
-def _encode_item(item):
- """Encode each item depending on its type"""
- if item == None:
- return (_pack_nil())
- elif type(item) == bool:
- return (_pack_bool(item))
- elif type(item) == int:
- return (_pack_int(item))
- elif type(item) == float:
- return (_pack_real(item))
- elif type(item) == dict:
- return (_pack_hash(item))
- elif type(item) == list:
- return (_pack_array(item))
- elif type(item) in (bytes, bytearray):
- return (_pack_blob(item))
- else:
- return (_pack_utf8(str(item)))
-
-def _encode_bool(item):
- """Encode a boolean value into a bytearray of one byte (0=false)"""
- if item:
- return b'1'
- else:
- return b'0'
-
-def _encode_array(item):
- """Encode an array, where each value is encoded recursively"""
- ret = bytes()
- for i in item:
- ret += _encode_item(i)
- return ret
-
-def _encode_hash(item):
- """Encode a hash, where each value is encoded recursively"""
- ret = bytes()
- for key, value in item.items():
- ret += _encode_tag(key)
- ret += _encode_item(value)
- return ret
-
-#
-# decode methods
-#
+ '''Encodes the given python structure in JSON, and converts the
+ result to bytes. Raises a TypeError if the given structure is
+ not serializable with JSON.'''
+ return json.dumps(items).encode('utf8')
def from_wire(data):
- if len(data) < 5:
- raise DecodeError("Data is too short to decode")
- wire_version, data = data[0:4], data[4:]
- wire_version = struct.unpack(">I", wire_version)[0]
- if wire_version != PROTOCOL_VERSION:
- raise DecodeError("Incorrect protocol version")
- return _decode_hash(data)
-
-def _decode_tag(data):
- if len(data) < 1:
- raise DecodeError("Data underrun while decoding")
- length = data[0]
- if len(data) - 1 < length:
- raise DecodeError("Data underrun while decoding")
- return [data[1:length + 1].decode(), data[length + 1:]]
-
-def _decode_item(data):
- if len(data) < 1:
- raise DecodeError("Data underrun while decoding")
- type_and_length_format = data[0]
- item_type = type_and_length_format & _ITEM_MASK
- length_format = type_and_length_format & _ITEM_LENGTH_MASK
-
- if item_type == _ITEM_NULL:
- data = data[1:]
- else:
- if length_format == _ITEM_LENGTH_8:
- if len(data) - 1 < 1:
- raise DecodeError("Data underrun while decoding")
- length = data[1]
- data = data[2:]
- elif length_format == _ITEM_LENGTH_16:
- if len(data) - 1 < 2:
- raise DecodeError("Data underrun while decoding")
- length = struct.unpack(">H", data[1:3])[0]
- data = data[3:]
- elif length_format == _ITEM_LENGTH_32:
- if len(data) - 1 < 4:
- raise DecodeError("Data underrun while decoding")
- length = struct.unpack(">I", data[1:5])[0]
- data = data[5:]
- if len(data) < length:
- raise DecodeError("Data underrun while decoding")
- item = data[0:length]
- data = data[length:]
-
- if item_type == _ITEM_BLOB:
- value = item
- elif item_type == _ITEM_BOOL:
- value = _decode_bool(item)
- elif item_type == _ITEM_INT:
- value = _decode_int(item)
- elif item_type == _ITEM_REAL:
- value = _decode_real(item)
- elif item_type == _ITEM_UTF8:
- value = str(item, 'utf-8')
- elif item_type == _ITEM_HASH:
- value = _decode_hash(item)
- elif item_type == _ITEM_LIST:
- value = _decode_array(item)
- elif item_type == _ITEM_NULL:
- value = None
- else:
- raise DecodeError("Unknown item type in decode: %02x" % item_type)
-
- return (value, data)
-
-def _decode_bool(data):
- return data == b'1'
-
-def _decode_int(data):
- return int(str(data, 'utf-8'))
-
-def _decode_real(data):
- return float(str(data, 'utf-8'))
-
-def _decode_hash(data):
- ret = {}
- while len(data) > 0:
- tag, data = _decode_tag(data)
- value, data = _decode_item(data)
- ret[tag] = value
- return ret
-
-def _decode_array(data):
- ret = []
- while len(data) > 0:
- value, data = _decode_item(data)
- ret.append(value)
- return ret
+ '''Decodes the given bytes and parses it with the builtin JSON
+ parser. Raises a ValueError if the data is not valid JSON.
+ Raises an AttributeError if the given object has no decode()
+ method (which should return a string).
+ '''
+ return json.loads(data.decode('utf8'))
if __name__ == "__main__":
import doctest
Modified: trunk/src/lib/python/isc/cc/tests/Makefile.am
==============================================================================
--- trunk/src/lib/python/isc/cc/tests/Makefile.am (original)
+++ trunk/src/lib/python/isc/cc/tests/Makefile.am Wed Jun 30 19:05:31 2010
@@ -1,4 +1,4 @@
-PYTESTS = data_test.py session_test.py test.py
+PYTESTS = message_test.py data_test.py session_test.py
# NOTE: test_session.py is to be run manually, so not automated.
EXTRA_DIST = $(PYTESTS)
EXTRA_DIST += sendcmd.py
Modified: trunk/src/lib/python/isc/cc/tests/session_test.py
==============================================================================
--- trunk/src/lib/python/isc/cc/tests/session_test.py (original)
+++ trunk/src/lib/python/isc/cc/tests/session_test.py Wed Jun 30 19:05:31 2010
@@ -39,10 +39,7 @@
pass
def send(self, data):
- #print("[XX] send called:")
- #print(data)
self.sendqueue.extend(data);
- pass
def readsent(self, length):
if length > len(self.sendqueue):
@@ -70,7 +67,6 @@
return result
def recv(self, length):
- #print("[XX] recv(" + str(length) + ") of " + str(len(self.recvqueue)))
if length > len(self.recvqueue):
raise Exception("Buffer underrun in test, does the test provide the right data?")
result = self.recvqueue[:length]
@@ -79,11 +75,19 @@
#print("[XX] queue now: " + str(self.recvqueue))
return result
- def addrecv(self, data):
- self.recvqueue.extend(data)
-
- def addrecvmsg(self, env, msg = None):
- self.addrecv(self.preparemsg(env, msg))
+ def addrecv(self, env, msg = None):
+ if type(env) == dict:
+ env = isc.cc.message.to_wire(env)
+ if type(msg) == dict:
+ msg = isc.cc.message.to_wire(msg)
+ length = 2 + len(env);
+ if msg:
+ length += len(msg)
+ self.recvqueue.extend(struct.pack("!I", length))
+ self.recvqueue.extend(struct.pack("!H", len(env)))
+ self.recvqueue.extend(env)
+ if msg:
+ self.recvqueue.extend(msg)
#
# We subclass the Session class we're testing here, only
@@ -120,7 +124,7 @@
sess = MySession()
sess.sendmsg({}, {"hello": "a"})
sent = sess._socket.readsentmsg();
- self.assertEqual(sent, b'\x00\x00\x00\x13\x00\x04SkanSkan\x05hello(\x01a')
+ self.assertEqual(sent, b'\x00\x00\x00\x12\x00\x02{}{"hello": "a"}')
sess.close()
self.assertRaises(SessionError, sess.sendmsg, {}, {"hello": "a"})
@@ -147,41 +151,37 @@
def test_session_recvmsg(self):
sess = MySession()
# {'to': "someone"}, {"hello": "a"}
- self.recv_and_compare(sess,
- b'\x00\x00\x00\x1f\x00\x10Skan\x02to(\x07someoneSkan\x05hello(\x01a',
- {'to': "someone"}, {"hello": "a"})
+ #self.recv_and_compare(sess,
+ # b'\x00\x00\x00\x1f\x00\x10Skan\x02to(\x07someoneSkan\x05hello(\x01a',
+ # {'to': "someone"}, {"hello": "a"})
# 'malformed' messages
# shouldn't some of these raise exceptions?
- self.recv_and_compare(sess,
- b'\x00',
- None, None)
- self.recv_and_compare(sess,
- b'\x00\x00\x00\x10',
- None, None)
- self.recv_and_compare(sess,
- b'\x00\x00\x00\x02\x00\x00',
- None, None)
- self.recv_and_compare(sess,
- b'\x00\x00\x00\x02\x00\x02',
- None, None)
- self.recv_and_compare(sess,
- b'',
- None, None)
-
- # incomplete data field
- sess._socket.addrecv(b'\x00\x00\x00\x1f\x00\x10Skan\x02to(\x07someoneSkan\x05hello(\x01')
- self.assertRaises(isc.cc.message.DecodeError, sess.recvmsg)
+ #self.recv_and_compare(sess,
+ # b'\x00',
+ # None, None)
+ #self.recv_and_compare(sess,
+ # b'\x00\x00\x00\x10',
+ # None, None)
+ #self.recv_and_compare(sess,
+ # b'\x00\x00\x00\x02\x00\x00',
+ # None, None)
+ #self.recv_and_compare(sess,
+ # b'\x00\x00\x00\x02\x00\x02',
+ # None, None)
+ #self.recv_and_compare(sess,
+ # b'',
+ # None, None)
+
# need to clear
sess._socket.recvqueue = bytearray()
# 'queueing' system
# sending message {'to': 'someone', 'reply': 1}, {"hello": "a"}
#print("sending message {'to': 'someone', 'reply': 1}, {'hello': 'a'}")
-
# get no message without asking for a specific sequence number reply
self.assertFalse(sess.has_queued_msgs())
- sess._socket.addrecv(b'\x00\x00\x00(\x00\x19Skan\x02to(\x07someone\x05reply&\x011Skan\x05hello(\x01a')
+ sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
env, msg = sess.recvmsg(False)
self.assertEqual(None, env)
self.assertTrue(sess.has_queued_msgs())
@@ -193,7 +193,7 @@
# ask for a differe sequence number reply (that doesn't exist)
# then ask for the one that is there
self.assertFalse(sess.has_queued_msgs())
- sess._socket.addrecv(b'\x00\x00\x00(\x00\x19Skan\x02to(\x07someone\x05reply&\x011Skan\x05hello(\x01a')
+ sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
env, msg = sess.recvmsg(False, 2)
self.assertEqual(None, env)
self.assertEqual(None, msg)
@@ -206,7 +206,7 @@
# ask for a differe sequence number reply (that doesn't exist)
# then ask for any message
self.assertFalse(sess.has_queued_msgs())
- sess._socket.addrecv(b'\x00\x00\x00(\x00\x19Skan\x02to(\x07someone\x05reply&\x011Skan\x05hello(\x01a')
+ sess._socket.addrecv({'to': 'someone', 'reply': 1}, {"hello": "a"})
env, msg = sess.recvmsg(False, 2)
self.assertEqual(None, env)
self.assertEqual(None, msg)
@@ -222,12 +222,12 @@
# send a new message, ask for specific message (get the first)
# then ask for any message (get the second)
self.assertFalse(sess.has_queued_msgs())
- sess._socket.addrecv(b'\x00\x00\x00(\x00\x19Skan\x02to(\x07someone\x05reply&\x011Skan\x05hello(\x01a')
+ sess._socket.addrecv({'to': 'someone', 'reply': 1}, {'hello': 'a'})
env, msg = sess.recvmsg(False, 2)
self.assertEqual(None, env)
self.assertEqual(None, msg)
self.assertTrue(sess.has_queued_msgs())
- sess._socket.addrecv(b'\x00\x00\x00\x1f\x00\x10Skan\x02to(\x07someoneSkan\x05hello(\x01b')
+ sess._socket.addrecv({'to': 'someone' }, {'hello': 'b'})
env, msg = sess.recvmsg(False, 1)
self.assertEqual({'to': 'someone', 'reply': 1 }, env)
self.assertEqual({"hello": "a"}, msg)
@@ -241,8 +241,8 @@
# ask for that specific message (get the second)
# then ask for any message (get the first)
self.assertFalse(sess.has_queued_msgs())
- sess._socket.addrecv(b'\x00\x00\x00\x1f\x00\x10Skan\x02to(\x07someoneSkan\x05hello(\x01b')
- sess._socket.addrecv(b'\x00\x00\x00(\x00\x19Skan\x02to(\x07someone\x05reply&\x011Skan\x05hello(\x01a')
+ sess._socket.addrecv({'to': 'someone' }, {'hello': 'b'})
+ sess._socket.addrecv({'to': 'someone', 'reply': 1}, {'hello': 'a'})
env, msg = sess.recvmsg(False, 1)
self.assertEqual({'to': 'someone', 'reply': 1}, env)
self.assertEqual({"hello": "a"}, msg)
@@ -266,29 +266,29 @@
sess = MySession()
sess.group_subscribe("mygroup")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x001\x00/Skan\x05group(\x07mygroup\x04type(\tsubscribe\x08instance(\x01*')
+ self.assertEqual(sent, b'\x00\x00\x00<\x00:{"group": "mygroup", "type": "subscribe", "instance": "*"}')
sess.group_subscribe("mygroup")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x001\x00/Skan\x05group(\x07mygroup\x04type(\tsubscribe\x08instance(\x01*')
+ self.assertEqual(sent, b'\x00\x00\x00<\x00:{"group": "mygroup", "type": "subscribe", "instance": "*"}')
sess.group_subscribe("mygroup", "my_instance")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x00;\x009Skan\x05group(\x07mygroup\x04type(\tsubscribe\x08instance(\x0bmy_instance')
+ self.assertEqual(sent, b'\x00\x00\x00F\x00D{"group": "mygroup", "type": "subscribe", "instance": "my_instance"}')
def test_group_unsubscribe(self):
sess = MySession()
sess.group_unsubscribe("mygroup")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x003\x001Skan\x05group(\x07mygroup\x04type(\x0bunsubscribe\x08instance(\x01*')
+ self.assertEqual(sent, b'\x00\x00\x00>\x00<{"group": "mygroup", "type": "unsubscribe", "instance": "*"}')
sess.group_unsubscribe("mygroup")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x003\x001Skan\x05group(\x07mygroup\x04type(\x0bunsubscribe\x08instance(\x01*')
+ self.assertEqual(sent, b'\x00\x00\x00>\x00<{"group": "mygroup", "type": "unsubscribe", "instance": "*"}')
sess.group_unsubscribe("mygroup", "my_instance")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x00=\x00;Skan\x05group(\x07mygroup\x04type(\x0bunsubscribe\x08instance(\x0bmy_instance')
+ self.assertEqual(sent, b'\x00\x00\x00H\x00F{"group": "mygroup", "type": "unsubscribe", "instance": "my_instance"}')
def test_group_sendmsg(self):
sess = MySession()
@@ -296,17 +296,17 @@
sess.group_sendmsg({ 'hello': 'a' }, "my_group")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x00W\x00HSkan\x04from(\ttest_name\x03seq&\x012\x02to(\x01*\x08instance(\x01*\x05group(\x08my_group\x04type(\x04sendSkan\x05hello(\x01a')
+ self.assertEqual(sent, b'\x00\x00\x00p\x00`{"from": "test_name", "seq": 2, "to": "*", "instance": "*", "group": "my_group", "type": "send"}{"hello": "a"}')
self.assertEqual(sess._sequence, 2)
sess.group_sendmsg({ 'hello': 'a' }, "my_group", "my_instance")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x00a\x00RSkan\x04from(\ttest_name\x03seq&\x013\x02to(\x01*\x08instance(\x0bmy_instance\x05group(\x08my_group\x04type(\x04sendSkan\x05hello(\x01a')
+ self.assertEqual(sent, b'\x00\x00\x00z\x00j{"from": "test_name", "seq": 3, "to": "*", "instance": "my_instance", "group": "my_group", "type": "send"}{"hello": "a"}')
self.assertEqual(sess._sequence, 3)
sess.group_sendmsg({ 'hello': 'a' }, "your_group", "your_instance")
sent = sess._socket.readsentmsg()
- self.assertEqual(sent, b'\x00\x00\x00e\x00VSkan\x04from(\ttest_name\x03seq&\x014\x02to(\x01*\x08instance(\ryour_instance\x05group(\nyour_group\x04type(\x04sendSkan\x05hello(\x01a')
+ self.assertEqual(sent, b'\x00\x00\x00~\x00n{"from": "test_name", "seq": 4, "to": "*", "instance": "your_instance", "group": "your_group", "type": "send"}{"hello": "a"}')
self.assertEqual(sess._sequence, 4)
def test_group_recvmsg(self):
@@ -318,11 +318,11 @@
sess = MySession()
sess.group_reply({ 'from': 'me', 'group': 'our_group', 'instance': 'other_instance', 'seq': 4}, {"hello": "a"})
sent = sess._socket.readsentmsg();
- self.assertEqual(sent, b'\x00\x00\x00o\x00`Skan\x04from(\ttest_name\x03seq&\x012\x02to(\x02me\x08instance(\x0eother_instance\x05reply&\x014\x05group(\tour_group\x04type(\x04sendSkan\x05hello(\x01a')
+ self.assertEqual(sent, b'\x00\x00\x00\x8b\x00{{"from": "test_name", "seq": 2, "to": "me", "instance": "other_instance", "reply": 4, "group": "our_group", "type": "send"}{"hello": "a"}')
sess.group_reply({ 'from': 'me', 'group': 'our_group', 'instance': 'other_instance', 'seq': 9}, {"hello": "a"})
sent = sess._socket.readsentmsg();
- self.assertEqual(sent, b'\x00\x00\x00o\x00`Skan\x04from(\ttest_name\x03seq&\x013\x02to(\x02me\x08instance(\x0eother_instance\x05reply&\x019\x05group(\tour_group\x04type(\x04sendSkan\x05hello(\x01a')
+ self.assertEqual(sent, b'\x00\x00\x00\x8b\x00{{"from": "test_name", "seq": 3, "to": "me", "instance": "other_instance", "reply": 9, "group": "our_group", "type": "send"}{"hello": "a"}')
if __name__ == "__main__":
More information about the bind10-changes
mailing list