Skip to content

Commit

Permalink
Refactor: move XML and CLOB tests to common code
Browse files Browse the repository at this point in the history
Don't duplicate them for PostgreSQL and Oracle, especially because they
will be needed for other backends in the future too.
  • Loading branch information
vadz committed Sep 13, 2017
1 parent 4744c17 commit 85159db
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 108 deletions.
110 changes: 110 additions & 0 deletions tests/common-tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,25 @@ class test_context_base
virtual table_creator_base* table_creator_3(session&) const = 0;
virtual table_creator_base* table_creator_4(session&) const = 0;

// Override this to return the table creator for a simple table containing
// an integer "id" column and CLOB "s" one.
//
// Returns null by default to indicate that CLOB is not supported.
virtual table_creator_base* table_creator_clob(session&) const { return NULL; }

// Override this to return the table creator for a simple table containing
// an integer "id" column and XML "x" one.
//
// Returns null by default to indicate that XML is not supported.
virtual table_creator_base* table_creator_xml(session&) const { return NULL; }

// Return the casts that must be used to convert the between the database
// XML type and the query parameters.
//
// By default no special casts are done.
virtual std::string to_xml(std::string const& x) const { return x; }
virtual std::string from_xml(std::string const& x) const { return x; }

// Override this if the backend doesn't handle floating point values
// correctly, i.e. writing a value and reading it back doesn't return
// *exactly* the same value.
Expand Down Expand Up @@ -4260,6 +4279,97 @@ TEST_CASE_METHOD(common_tests, "String length", "[core][string][length]")
CHECK(vout[2].length() == 20);
}

// Helper function used in two tests below.
static std::string make_long_xml_string()
{
std::string s;
s.reserve(6 + 200*26 + 7);

s += "<file>";
for (int i = 0; i != 200; ++i)
{
s += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
s += "</file>";

return s;
}

TEST_CASE_METHOD(common_tests, "CLOB", "[core][clob]")
{
soci::session sql(backEndFactory_, connectString_);

auto_table_creator tableCreator(tc_.table_creator_clob(sql));
if (!tableCreator.get())
{
WARN("CLOB type not supported by the database, skipping the test.");
return;
}

long_string s1; // empty
sql << "insert into soci_test(id, s) values (1, :s)", use(s1);

long_string s2;
s2.value = "hello";
sql << "select s from soci_test where id = 1", into(s2);

CHECK(s2.value.size() == 0);

s1.value = make_long_xml_string();

sql << "update soci_test set s = :s where id = 1", use(s1);

sql << "select s from soci_test where id = 1", into(s2);

CHECK(s2.value == s1.value);
}

TEST_CASE_METHOD(common_tests, "XML", "[core][xml]")
{
soci::session sql(backEndFactory_, connectString_);

auto_table_creator tableCreator(tc_.table_creator_xml(sql));
if (!tableCreator.get())
{
WARN("XML type not supported by the database, skipping the test.");
return;
}

int id = 1;
xml_type xml;

// The extra new line is a special hack for Oracle: its getCLOBVal()
// seems to reformat the returned XML and, in particular, appends a new
// line to it if its last line doesn't contain one already. So if we didn't
// append it here the check for round trip below would fail because of the
// extra new line.
xml.value = make_long_xml_string() + "\n";

sql << "insert into soci_test (id, x) values (:1, "
<< tc_.to_xml(":2")
<< ")",
use(id), use(xml);

xml_type xml2;

sql << "select "
<< tc_.from_xml("x")
<< " from soci_test where id = :1",
into(xml2), use(id);

CHECK(xml.value == xml2.value);

sql << "update soci_test set x = null where id = :1", use(id);

indicator ind;
sql << "select "
<< tc_.from_xml("x")
<< " from soci_test where id = :1",
into(xml2, ind), use(id);

CHECK(ind == i_null);
}

} // namespace test_cases

} // namespace tests
Expand Down
98 changes: 40 additions & 58 deletions tests/oracle/test-oracle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1421,64 +1421,6 @@ TEST_CASE("Bulk iterators", "[oracle][bulkiters]")
sql << "drop table t";
}

// XML and big string test
TEST_CASE("XML and big string", "[oracle][xml]")
{
session sql(backEnd, connectString);

sql << "create table xml_test (id integer, x xmltype)";

int id = 1;
xml_type xml;
xml.value = "<file>";
for (int i = 0; i != 200; ++i)
{
xml.value += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
xml.value += "</file>";

sql << "insert into xml_test (id, x) values (:1, xmltype(:2))", use(id), use(xml);

xml_type xml2;

sql << "select t.x.getCLOBVal() from xml_test t where id = :1", into(xml2), use(id);

// note: getCLOBVal() returns XML value with newline added at the end
CHECK(xml.value + '\n' == xml2.value);

sql << "update xml_test set x = null where id = :1", use(id);

indicator ind;
sql << "select t.x.getCLOBVal() from xml_test t where id = :1", into(xml2, ind), use(id);

CHECK(ind == i_null);

sql << "drop table xml_test";

// additional test for empty and non-empty long_string

sql << "create table long_string_test (id integer, s clob)";

long_string s1; // empty
sql << "insert into long_string_test(id, s) values (1, :s)", use(s1);

long_string s2;
s2.value = "hello";
sql << "select s from long_string_test where id = 1", into(s2);

CHECK(s2.value.size() == 0);

s1.value = xml.value; // some long value

sql << "update long_string_test set s = :s where id = 1", use(s1);

sql << "select s from long_string_test where id = 1", into(s2);

CHECK(s2.value == xml.value);

sql << "drop table long_string_test";
}

//
// Support for soci Common Tests
//
Expand Down Expand Up @@ -1524,6 +1466,24 @@ struct table_creator_four : public table_creator_base
}
};

struct table_creator_for_xml : table_creator_base
{
table_creator_for_xml(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, x xmltype)";
}
};

struct table_creator_for_clob : table_creator_base
{
table_creator_for_clob(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, s clob)";
}
};

class test_context :public test_context_base
{
public:
Expand Down Expand Up @@ -1551,6 +1511,28 @@ class test_context :public test_context_base
return new table_creator_four(s);
}

table_creator_base* table_creator_clob(soci::session& s) const
{
return new table_creator_for_clob(s);
}

table_creator_base* table_creator_xml(soci::session& s) const
{
return new table_creator_for_xml(s);
}

std::string to_xml(std::string const& x) const
{
return "xmltype(" + x + ")";
}

std::string from_xml(std::string const& x) const
{
// Notice that using just x.getCLOBVal() doesn't work, only
// table.x.getCLOBVal() or (x).getCLOBVal(), as used here, does.
return "(" + x + ").getCLOBVal()";
}

std::string to_date_time(std::string const &datdt_string) const
{
return "to_date('" + datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')";
Expand Down
78 changes: 28 additions & 50 deletions tests/postgresql/test-postgresql.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,56 +1038,6 @@ TEST_CASE("Bulk iterators", "[postgresql][bulkiters]")
sql << "drop table t";
}

// Test support for XML and long string wrapper types
TEST_CASE("XML wrapper type", "[postgresql][xml]")
{
session sql(backEnd, connectString);

sql << "create table xml_test (id integer, x xml)";

int id = 1;
xml_type xml;
xml.value = "<file>";
for (int i = 0; i != 200; ++i)
{
xml.value += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
xml.value += "</file>";

sql << "insert into xml_test (id, x) values (:1, :2)", use(id), use(xml);

xml_type xml2;

sql << "select x from xml_test where id = :1", into(xml2), use(id);

CHECK(xml.value == xml2.value);

sql << "drop table xml_test";

// additional test for empty and non-empty long_string

sql << "create table long_string_test (id integer, s text)";

long_string s1; // empty
sql << "insert into long_string_test(id, s) values (1, :s)", use(s1);

long_string s2;
s2.value = "hello";
sql << "select s from long_string_test where id = 1", into(s2);

CHECK(s2.value.size() == 0);

s1.value = xml.value; // some long value

sql << "update long_string_test set s = :s where id = 1", use(s1);

sql << "select s from long_string_test where id = 1", into(s2);

CHECK(s2.value == xml.value);

sql << "drop table long_string_test";
}

//
// Support for soci Common Tests
//
Expand Down Expand Up @@ -1135,6 +1085,24 @@ struct table_creator_for_get_affected_rows : table_creator_base
}
};

struct table_creator_for_xml : table_creator_base
{
table_creator_for_xml(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, x xml)";
}
};

struct table_creator_for_clob : table_creator_base
{
table_creator_for_clob(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, s text)";
}
};

// Common tests context
class test_context : public test_context_base
{
Expand Down Expand Up @@ -1163,6 +1131,16 @@ class test_context : public test_context_base
return new table_creator_for_get_affected_rows(s);
}

table_creator_base* table_creator_xml(soci::session& s) const
{
return new table_creator_for_xml(s);
}

table_creator_base* table_creator_clob(soci::session& s) const
{
return new table_creator_for_clob(s);
}

std::string to_date_time(std::string const &datdt_string) const
{
return "timestamptz(\'" + datdt_string + "\')";
Expand Down

0 comments on commit 85159db

Please sign in to comment.