diff options
Diffstat (limited to 'odb-tests/common/readonly')
-rw-r--r-- | odb-tests/common/readonly/buildfile | 40 | ||||
-rw-r--r-- | odb-tests/common/readonly/driver.cxx | 324 | ||||
-rw-r--r-- | odb-tests/common/readonly/test.hxx | 225 | ||||
-rw-r--r-- | odb-tests/common/readonly/testscript | 53 |
4 files changed, 642 insertions, 0 deletions
diff --git a/odb-tests/common/readonly/buildfile b/odb-tests/common/readonly/buildfile new file mode 100644 index 0000000..2d83cf1 --- /dev/null +++ b/odb-tests/common/readonly/buildfile @@ -0,0 +1,40 @@ +# file : common/readonly/buildfile +# license : GNU GPL v2; see accompanying LICENSE file + +import libodb = libodb%lib{odb} + +libs = + +for db: $databases + import libs += libodb-$db%lib{odb-$db} + +import libs += lib{common} + +exe{driver}: {hxx cxx}{* -*-odb -*-odb-*} {hxx ixx cxx}{test-odb} testscript + +# Introduce the metadata library target to make sure the libodb library is +# resolved for the odb_compile ad hoc rule (see build/root.build for details). +# +libue{test-meta}: $libodb + +<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta} + +for db: $databases +{ + exe{driver}: {hxx ixx cxx}{test-odb-$db}: include = $multi + <{hxx ixx cxx}{test-odb-$db}>: hxx{test} libue{test-meta} +} + +exe{driver}: libue{test-meta} $libs + +# Specify the ODB custom options to be used by the odb_compile ad hoc rule +# (see build/root.build for details). +# +odb_options = --table-prefix readonly_ \ + --generate-schema + +cxx.poptions =+ "-I$out_base" "-I$src_base" + +# Testscript's run-time prerequisites. +# +exe{driver}: ../../alias{database-client}: include = adhoc diff --git a/odb-tests/common/readonly/driver.cxx b/odb-tests/common/readonly/driver.cxx new file mode 100644 index 0000000..3531e57 --- /dev/null +++ b/odb-tests/common/readonly/driver.cxx @@ -0,0 +1,324 @@ +// file : common/readonly/driver.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +// Test readonly members/objects. Also test that const members are +// treated as readonly. For other const member tests, see the const- +// member test. +// + +#include <memory> // std::unique_ptr +#include <iostream> + +#include <odb/database.hxx> +#include <odb/transaction.hxx> + +#include <libcommon/config.hxx> // MULTI_DATABASE +#include <libcommon/common.hxx> + +#include "test.hxx" +#include "test-odb.hxx" + +#undef NDEBUG +#include <cassert> + +using namespace std; +using namespace odb::core; + +int +main (int argc, char* argv[]) +{ + try + { + unique_ptr<database> db (create_database (argc, argv)); + + // Simple. + // + { + simple o (1, 1); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + o.ro++; + const_cast<unsigned long&> (o.co)++; + o.rw++; + + { + transaction t (db->begin ()); + db->update (o); + t.commit (); + } + + { + transaction t (db->begin ()); + db->load<simple> (1, o); + t.commit (); + } + + assert (o.ro == 1 && o.co == 1 && o.rw == 2); + } + + // Pointer. + // + { + pointer p (1, new pointer (2)); + unique_ptr<pointer> p1 (new pointer (3)); + + { + transaction t (db->begin ()); + db->persist (p); + db->persist (p.ro); + db->persist (*p1); + t.commit (); + } + + delete p.ro; + p.ro = p1.release (); + const_cast<pointer*&> (p.co) = p.ro; + p.rw = p.ro; + + { + transaction t (db->begin ()); + db->update (p); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<pointer> p (db->load<pointer> (1)); + t.commit (); + + assert (p->ro->id == 2 && p->co->id == 2 && p->rw->id == 3); + } + } + + // Composite. + // + { + composite o (1, 1); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + o.ro.v++; + o.ro.ro++; + const_cast<unsigned long&> (o.ro.co)++; + o.ro.rw++; + + value& co (const_cast<value&> (o.co)); + co.v++; + co.ro++; + const_cast<unsigned long&> (co.co)++; + co.rw++; + + o.rw.v++; + o.rw.ro++; + const_cast<unsigned long&> (o.rw.co)++; + o.rw.rw++; + + o.v.v++; + + { + transaction t (db->begin ()); + db->update (o); + t.commit (); + } + + { + transaction t (db->begin ()); + db->load<composite> (1, o); + t.commit (); + } + + assert (o.ro.v == 1 && + o.ro.ro == 1 && + o.ro.co == 1 && + o.ro.rw == 1 && + + o.co.v == 1 && + o.co.ro == 1 && + o.co.co == 1 && + o.co.rw == 1 && + + o.rw.v == 1 && + o.rw.ro == 1 && + o.rw.co == 1 && + o.rw.rw == 2 && + + o.v.v == 1); + } + + // Container. + // + { + typedef vector<unsigned long> ulongs; + + container o (1); + + o.ro.push_back (1); + o.ro.push_back (2); + + ulongs& co (const_cast<ulongs&> (o.co)); + co.push_back (1); + co.push_back (2); + + o.rw.push_back (1); + o.rw.push_back (2); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + o.ro[0]++; + o.ro.pop_back (); + + co[0]++; + co.pop_back (); + + o.rw[0]++; + o.rw.pop_back (); + + { + transaction t (db->begin ()); + db->update (o); + t.commit (); + } + + { + transaction t (db->begin ()); + db->load<container> (1, o); + t.commit (); + } + + assert (o.ro.size () == 2 && o.ro[0] == 1 && o.ro[1] == 2 && + o.co.size () == 2 && o.co[0] == 1 && o.co[1] == 2 && + o.rw.size () == 1 && o.rw[0] == 2); + } + + // Readonly object. + // + { +#ifndef MULTI_DATABASE + typedef odb::object_traits_impl<simple_object, odb::id_common> so_traits; + typedef odb::object_traits_impl<ro_object, odb::id_common> ro_traits; + typedef odb::object_traits_impl<rw_object, odb::id_common> rw_traits; + + assert (so_traits::column_count == + so_traits::id_column_count + so_traits::readonly_column_count); + + assert (ro_traits::column_count == + ro_traits::id_column_count + ro_traits::readonly_column_count); + + assert (rw_traits::column_count != + rw_traits::id_column_count + rw_traits::readonly_column_count); +#endif + + simple_object so (1, 1); + ro_object ro_o (1, 1); + rw_object rw_o (1, 1); + + ro_o.cr.push_back (1); + ro_o.cr.push_back (2); + + rw_o.cr.push_back (1); + rw_o.cr.push_back (2); + + { + transaction t (db->begin ()); + db->persist (so); + db->persist (ro_o); + db->persist (rw_o); + t.commit (); + } + + rw_o.sv++; + rw_o.rw_sv++; + + { + transaction t (db->begin ()); + //db->update (so); // Compile error. + //db->update (ro_o); // Compile error. + db->update (rw_o); + t.commit (); + } + + { + transaction t (db->begin ()); + db->load (1, so); + db->load (1, ro_o); + db->load (1, rw_o); + t.commit (); + } + + assert (rw_o.sv == 1 && rw_o.rw_sv == 2); + } + + // Readonly object. + // + { + wrapper o (1, 1); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + *o.pl = 2; + *o.cpl = 2; + o.pcl.reset (new unsigned long (2)); + const_cast<unsigned long&> (*o.cpcl) = 2; + + { + transaction t (db->begin ()); + db->update (o); + t.commit (); + } + + { + transaction t (db->begin ()); + db->load<wrapper> (1, o); + t.commit (); + } + + assert (*o.pl == 2 && *o.cpl == 2 && *o.pcl == 2 && *o.cpcl == 1); + } + + // Readonly object with auto id. + // + { + ro_auto o1 (1); + ro_auto o2 (2); + + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<ro_auto> p1 (db->load<ro_auto> (o1.id)); + unique_ptr<ro_auto> p2 (db->load<ro_auto> (o2.id)); + t.commit (); + + assert (p1->num == o1.num); + assert (p2->num == o2.num); + } + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/odb-tests/common/readonly/test.hxx b/odb-tests/common/readonly/test.hxx new file mode 100644 index 0000000..45797b6 --- /dev/null +++ b/odb-tests/common/readonly/test.hxx @@ -0,0 +1,225 @@ +// file : common/readonly/test.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST_HXX +#define TEST_HXX + +#include <vector> +#include <memory> // std::unique_ptr + +#include <odb/core.hxx> + +// Simple readonly object. +// +#pragma db object +struct simple +{ + simple (unsigned long i, unsigned long x) + : id (i), ro (x), co (x), rw (x) + { + } + + simple (): co (0) {} + + #pragma db id + unsigned long id; + + #pragma db readonly + unsigned long ro; + + const unsigned long co; + + unsigned long rw; +}; + +// Readonly pointer. +// +#pragma db object +struct pointer +{ + pointer (unsigned long i, pointer* p = 0): id (i), ro (p), co (p), rw (p) {} + pointer (): ro (0), co (0), rw (0) {} + + ~pointer () + { + delete ro; + + if (co != ro) + delete co; + + if (rw != ro && rw != co) + delete rw; + } + + #pragma db id + unsigned long id; + + #pragma db readonly + pointer* ro; + + pointer* const co; + + pointer* rw; +}; + +// Composite readonly value as well as simple readonly value inside +// a composite. +// +#pragma db value readonly +struct ro_value +{ + ro_value () {} + ro_value (unsigned long x): v (x) {} + + unsigned long v; +}; + +#pragma db value +struct value: ro_value +{ + value (): co (0) {} + value (unsigned long x): ro_value (x), ro (x), co (x), rw (x) {} + + #pragma db readonly + unsigned long ro; + + const unsigned long co; + + unsigned long rw; +}; + +#pragma db object +struct composite +{ + composite (unsigned long i, unsigned long x) + : id (i), ro (x), co (x), rw (x), v (x) + { + } + + composite () {} + + #pragma db id + unsigned long id; + + #pragma db readonly + value ro; + + const value co; + + value rw; + ro_value v; +}; + +// Readonly container. +// +#pragma db object +struct container +{ + container (unsigned long i): id (i) {} + container () {} + + #pragma db id + unsigned long id; + + #pragma db readonly + std::vector<unsigned long> ro; + + const std::vector<unsigned long> co; + + std::vector<unsigned long> rw; +}; + +// Readonly object. +// +#pragma db object readonly +struct simple_object +{ + simple_object (unsigned long i, unsigned long x): id (i), sv (x) {} + simple_object () {} + + #pragma db id + unsigned long id; + + unsigned long sv; +}; + +#pragma db object +struct object +{ + object (unsigned long i, unsigned long x): id (i), sv (x) {} + object () {} + + #pragma db id + unsigned long id; + + unsigned long sv; +}; + +#pragma db object readonly +struct ro_object: object +{ + ro_object (unsigned long i, unsigned long x) + : object (i, x), cv (x) + { + } + + ro_object () {} + + value cv; + std::vector<unsigned long> cr; +}; + +#pragma db object +struct rw_object: ro_object +{ + rw_object (unsigned long i, unsigned long x) + : ro_object (i, x), rw_sv (x) + { + } + + rw_object () {} + + unsigned long rw_sv; +}; + +// Readonly wrappers. Here we make sure that only const wrappers with +// const wrapped types are automatically treated as readonly. +// +#pragma db object +struct wrapper +{ + wrapper (unsigned long i, unsigned long x) + : id (i), + pl (new unsigned long (x)), + cpl (new unsigned long (x)), + pcl (new unsigned long (x)), + cpcl (new unsigned long (x)) + { + } + + wrapper () {} + + #pragma db id + unsigned long id; + + std::unique_ptr<unsigned long> pl; + const std::unique_ptr<unsigned long> cpl; + std::unique_ptr<const unsigned long> pcl; + const std::unique_ptr<const unsigned long> cpcl; +}; + +// Readonly object with auto id. +// +#pragma db object readonly +struct ro_auto +{ + ro_auto (unsigned long n): num (n) {} + ro_auto () {} + + #pragma db id auto + unsigned long id; + + unsigned long num; +}; + +#endif // TEST_HXX diff --git a/odb-tests/common/readonly/testscript b/odb-tests/common/readonly/testscript new file mode 100644 index 0000000..491b55b --- /dev/null +++ b/odb-tests/common/readonly/testscript @@ -0,0 +1,53 @@ +# file : common/readonly/testscript +# license : GNU GPL v2; see accompanying LICENSE file + +.include ../../database-options.testscript + +: mysql +: +if $mysql +{ + .include ../../mysql.testscript + + $create_schema; + $* +} + +: sqlite +: +if $sqlite +{ + .include ../../sqlite.testscript + + $* +} + +: pgsql +: +if $pgsql +{ + .include ../../pgsql.testscript + + $create_schema; + $* +} + +: oracle +: +if $oracle +{ + .include ../../oracle.testscript + + $create_schema; + $* +} + +: mssql +: +if $mssql +{ + .include ../../mssql.testscript + + $create_schema; + $* +} |