diff options
Diffstat (limited to 'odb-tests/common/access')
-rw-r--r-- | odb-tests/common/access/buildfile | 45 | ||||
-rw-r--r-- | odb-tests/common/access/driver.cxx | 262 | ||||
-rw-r--r-- | odb-tests/common/access/test.hxx | 592 | ||||
-rw-r--r-- | odb-tests/common/access/testscript | 33 |
4 files changed, 932 insertions, 0 deletions
diff --git a/odb-tests/common/access/buildfile b/odb-tests/common/access/buildfile new file mode 100644 index 0000000..f1264d9 --- /dev/null +++ b/odb-tests/common/access/buildfile @@ -0,0 +1,45 @@ +# file : common/access/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 access_ \ + --generate-schema \ + --accessor-regex '#(.+)#Get\u\1#' \ + --modifier-regex '#(.+)#Set\u\1#' + +cxx.poptions =+ "-I$out_base" "-I$src_base" + +# Testscript's run-time prerequisites. +# +# @@ BUILD2: Eventually we should be able to mark it as test.input once +# this is supported for testscript tests. +# +exe{driver}: ../../alias{database-client}: include = adhoc diff --git a/odb-tests/common/access/driver.cxx b/odb-tests/common/access/driver.cxx new file mode 100644 index 0000000..b40e73c --- /dev/null +++ b/odb-tests/common/access/driver.cxx @@ -0,0 +1,262 @@ +// file : common/access/driver.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +// Test accessor/modifier expressions. +// + +#include <memory> // std::unique_ptr +#include <iostream> + +#include <odb/database.hxx> +#include <odb/transaction.hxx> + +#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)); + + // Test basic accessor/modifier functionality. + // + { + using namespace test1; + + object o (1, 623, 723); + o.i1 () = 123; + o.i2 (223); + o.i3 () = 323; + o.i4 () = 423; + o.set_i5 (523); + o.s1 ("1bc"); + memcpy (o.b1 (), "123456789012345", 16); + o.b2 ("123456789012345"); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (o.id ())); + t.commit (); + + assert (o == *p); + } + } + + // Test composite accessor/modifier functionality. + // + { + using namespace test2; + + object o (1); + + o.v1 () = value (1123, 1234); + o.v2 (value (2123, 2234)); + o.v3_i1 (3123); + o.v3_i2 (3223); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (o.id ())); + t.commit (); + + assert (o == *p); + } + } + + // Test object pointer accessor/modifier functionality. + // + { + using namespace test3; + + object2 o (1); + o.p1 ().reset (new object1 (1)); + o.p2 (object1_ptr (new object1 (2))); + + { + transaction t (db->begin ()); + const object1_ptr& ptr (o.p1 ()); + db->persist (ptr); + db->persist (o.p2 ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object2> p (db->load<object2> (o.id ())); + t.commit (); + + assert (p->p1 ()->id () == o.p1 ()->id () && + p->p2 ()->id () == o.p2 ()->id ()); + } + } + + // Test container accessor/modifier functionality. + // + { + using namespace test4; + + object o (1); + o.c1 ().push_back (1123); + o.c1 ().push_back (1124); + o.c1 ().push_back (1125); + + { + std::vector<int> v; + v.push_back (2123); + v.push_back (2124); + v.push_back (2125); + o.c2 (v); + } + + o.v1 ().c1 ().push_back (1123); + o.v1 ().c1 ().push_back (1124); + o.v1 ().c1 ().push_back (1125); + + { + std::vector<int> v; + v.push_back (2123); + v.push_back (2124); + v.push_back (2125); + o.v1 ().c2 (v); + } + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (o.id ())); + t.commit (); + + assert (o == *p); + } + } + + // Test id accessor/modifier functionality. + // + { + using namespace test5; + + object1 o1; + object2 o2; + object3 o3; + object4 o4; + o4.id (uuid ("\x60\x1D\x17\xF0-\x60\x05-\x47\x23-\x95\x37-" + "\xC1\xF8\x94\x41\x2B\xEC")); + + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + db->persist (o3); + db->persist (o4); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object1> p1 (db->load<object1> (o1.id ())); + unique_ptr<object2> p2 (db->load<object2> (o2.id ())); + unique_ptr<object3> p3 (db->load<object3> (o3.id_)); + unique_ptr<object4> p4 (db->load<object4> (o4.id ())); + t.commit (); + } + } + + // Test version accessor/modifier functionality. + // + { + using namespace test6; + + object1 o1 (1); + object2 o2; + object3 o3 (1); + + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + db->persist (o3); + t.commit (); + + assert (o1.version () == 1); + assert (o2.version () == 1); + assert (o3.version_ == 1); + } + + { + transaction t (db->begin ()); + db->update (o1); + db->update (o2); + db->update (o3); + t.commit (); + + assert (o1.version () == 2); + assert (o2.version () == 2); + assert (o3.version_ == 2); + } + } + + // Test basic accessor/modifier functionality. + // + { + using namespace test7; + + object o (1); + o.i1 () = 123; + o.set_i2 (223); + o.setI3 (323); + o.seti4 (423); + o.i5 () = 523; + o.i6 () = 623; + o.SetI7 (723); + memcpy (o.b1 (), "123456789012345", 16); + o.b2 ("123456789012345"); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (o.id_)); + t.commit (); + + assert (o == *p); + } + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/odb-tests/common/access/test.hxx b/odb-tests/common/access/test.hxx new file mode 100644 index 0000000..3a3424d --- /dev/null +++ b/odb-tests/common/access/test.hxx @@ -0,0 +1,592 @@ +// file : common/access/test.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST_HXX +#define TEST_HXX + +#include <string> +#include <vector> +#include <cstring> // std::memcpy, std::memcmp, std::memset +#include <memory> // std::unique_ptr +#include <utility> // std::move + +#include <odb/core.hxx> + +#ifdef ODB_COMPILER +# if defined(ODB_DATABASE_MYSQL) +# define BINARY16_TYPE "BINARY(16)" +# elif defined(ODB_DATABASE_SQLITE) +# define BINARY16_TYPE "BLOB" +# elif defined(ODB_DATABASE_PGSQL) +# define BINARY16_TYPE "BYTEA" +# elif defined(ODB_DATABASE_ORACLE) +# define BINARY16_TYPE "RAW(16)" +# elif defined(ODB_DATABASE_MSSQL) +# define BINARY16_TYPE "BINARY(16)" +# elif defined(ODB_DATABASE_COMMON) +# define BINARY16_TYPE "" +# else +# error unknown database +# endif +#endif + +// Test basic accessor/modifier functionality. +// +#pragma db namespace table("t1_") +namespace test1 +{ + #pragma db object + struct object + { + object (): i6_ (0), i7_ (0) {} + object (unsigned long id, int i6, int i7): id_ (id), i6_ (i6), i7_ (i7) {} + + public: + unsigned long id () const {return id_;} + void id (unsigned long id) {id_ = id;} + private: + #pragma db id access(id) + unsigned long id_; + + public: + int i1 () const {return i1_;} + int& i1 () {return i1_;} + private: + #pragma db access(i1) + int i1_; + + public: + int i2 () const {return i2_;} + void i2 (int i2) {i2_ = i2;} + private: + #pragma db access(i2) + int i2_; + + // Prefer reference modifier. + // + public: + int i3 () const {return i3_;} + int& i3 () {return i3_;} + void i3 (int i3); + private: + #pragma db access(i3) + int i3_; + + // Prefer reference modifier (reverse function order). + // + public: + int i4 () const {return i4_;} + void i4 (int i4); + int& i4 () {return i4_;} + private: + #pragma db access(i4) + int i4_; + + public: + int get_i5 () const {return i5_;} + void set_i5 (int i5) {i5_ = i5;} + private: + #pragma db get(get_i5) set(set_i5) + int i5_; + + // Const member via reference. + // + public: + const int& i6 () const {return i6_;} + private: + #pragma db get(i6) set(const_cast<int&> (this.i6 ())) + const int i6_; + + // Const member via modifier. + // + public: + int i7 () const {return i7_;} + void i7 (int i7) const {const_cast<int&> (i7_) = i7;} + private: + #pragma db access(i7) + const int i7_; + + public: + const char* s1 () const {return s1_.c_str ();} + void s1 (const char* s1) {s1_ = s1;} + //std::string s1 () const {return s1_;} + //void s1 (std::string s1) {s1_ = s1;} + private: + #pragma db get(s1) set(s1((?).c_str ())) + //#pragma db access(s1) + std::string s1_; + + // Array member via ref. + // + public: + const char* b1 () const {return b1_;} + char* b1 () {return b1_;} + private: + #pragma db type(BINARY16_TYPE) access(b1) + char b1_[16]; + + // Array member via modifier. + // + public: + const char* b2 () const {return b2_;} + void b2 (const char* b2) {std::memcpy (b2_, b2, sizeof (b2_));} + private: + #pragma db type(BINARY16_TYPE) access(b2) + char b2_[16]; + + public: + bool operator== (const object& o) const + { + return id_ == o.id_ && + i1_ == o.i1_ && + i2_ == o.i2_ && + i3_ == o.i3_ && + i4_ == o.i4_ && + i5_ == o.i5_ && + i6_ == o.i6_ && + i7_ == o.i7_ && + s1_ == o.s1_ && + std::memcmp (b1_, o.b1_, sizeof (b1_)) == 0 && + std::memcmp (b2_, o.b2_, sizeof (b2_)) == 0; + } + }; +} + +// Test composite accessor/modifier functionality. +// +#pragma db namespace table("t2_") +namespace test2 +{ + #pragma db value + struct value + { + value () {} + value (int i1, int i2): i1_ (i1), i2_ (i2) {} + + bool operator== (const value& v) const + { + return i1_ == v.i1_ && i2_ == v.i2_; + } + + public: + int i1 () const {return i1_;} + int& i1 () {return i1_;} + private: + #pragma db access(i1) + int i1_; + + public: + int i2 () const {return i2_;} + void i2 (int i2) {i2_ = i2;} + private: + #pragma db access(i2) + int i2_; + }; + + #pragma db object + struct object + { + object () {} + object (unsigned long id): id_ (id) {} + + bool operator== (const object& o) const + { + return id_ == o.id_ && + v1_ == o.v1_ && + v2_ == o.v2_ && + v3_ == o.v3_; + } + + public: + unsigned long id () const {return id_;} + void id (unsigned long id) {id_ = id;} + private: + #pragma db id access(id) + unsigned long id_; + + public: + const value& v1 () const {return v1_;} + value& v1 () {return v1_;} + private: + #pragma db access(v1) + value v1_; + + public: + const value& v2 () const {return v2_;} + void v2 (const value& v2) {v2_ = v2;} + private: + #pragma db access(v2) + value v2_; + + public: + int v3_i1 () const {return v3_.i1 ();} + int v3_i2 () const {return v3_.i2 ();} + void v3_i1 (int i1) {v3_.i1 () = i1;} + void v3_i2 (int i2) {v3_.i2 (i2);} + private: + #pragma db get(test2::value (this.v3_i1 (), this.v3_i2 ())) \ + set(this.v3_i1 ((?).i1 ()); this.v3_i2 ((?).i2 ())) + value v3_; + }; +} + +// Test object pointer accessor/modifier functionality. +// +#pragma db namespace table("t3_") +namespace test3 +{ + struct object1; + + typedef std::unique_ptr<object1> object1_ptr; + + #pragma db object pointer(object1_ptr) + struct object1 + { + object1 () {} + object1 (unsigned long id): id_ (id) {} + + public: + unsigned long id () const {return id_;} + void id (unsigned long id) {id_ = id;} + private: + #pragma db id access(id) + unsigned long id_; + }; + + #pragma db object + struct object2 + { + object2 () {} + object2 (unsigned long id): id_ (id) {} + + public: + unsigned long id () const {return id_;} + void id (unsigned long id) {id_ = id;} + private: + #pragma db id access(id) + unsigned long id_; + + public: + const object1_ptr& p1 () const {return p1_;} + object1_ptr& p1 () {return p1_;} + private: + #pragma db access(p1) + object1_ptr p1_; + + public: + const object1_ptr& p2 () const {return p2_;} + + void p2 (object1_ptr p2) {p2_ = std::move (p2);} + + private: + #pragma db get(p2) set(p2 (std::move (?))) + + object1_ptr p2_; + }; +} + +// Test container accessor/modifier functionality. +// +#pragma db namespace table("t4_") +namespace test4 +{ + #pragma db value + struct value + { + value (): c3_ (3, 999) {} + value (int v): c1_ (3, v), c2_ (3, v + 1), c3_ (3, v + 2) {} + + bool operator== (const value& v) const + { + return c1_ == v.c1_ && c2_ == v.c2_ && c3_ == v.c3_; + } + + public: + const std::vector<int>& c1 () const {return c1_;} + std::vector<int>& c1 () {return c1_;} + private: + #pragma db access(c1) + std::vector<int> c1_; + + public: + const std::vector<int>& c2 () const {return c2_;} + void c2 (const std::vector<int>& c2) {c2_ = c2;} + private: + #pragma db access(c2) + std::vector<int> c2_; + + public: + const std::vector<int> c3_; + }; + + #pragma db object + struct object + { + object () {} + object (unsigned long id): id_ (id), c3_ (3, 3123), v2_ (2123) {} + + bool operator== (const object& o) const + { + return id_ == o.id_ && + c1_ == o.c1_ && + c2_ == o.c2_ && + c3_ == o.c3_ && + v1_ == o.v1_ && + v2_ == o.v2_; + } + + public: + unsigned long id () const {return id_;} + void id (unsigned long id) {id_ = id;} + private: + #pragma db id access(id) + unsigned long id_; + + public: + const std::vector<int>& c1 () const {return c1_;} + std::vector<int>& c1 () {return c1_;} + private: + #pragma db access(c1) + std::vector<int> c1_; + + public: + const std::vector<int>& c2 () const {return c2_;} + void c2 (const std::vector<int>& c2) {c2_ = c2;} + private: + #pragma db access(c2) + std::vector<int> c2_; + + public: + const std::vector<int>& c3 () const {return c3_;} + private: + #pragma db get(c3) set(const_cast<std::vector<int>&> (this.c3 ())) + const std::vector<int> c3_; + + public: + const value& v1 () const {return v1_;} + value& v1 () {return v1_;} + private: + #pragma db access(v1) + value v1_; + + public: + const value v2_; + }; +} + +// Test id accessor/modifier functionality. +// +#pragma db namespace table("t5_") +namespace test5 +{ + #pragma db object + struct object1 + { + object1 (): id_ (0) {} + + public: + unsigned long id () const {return id_;} + void id (unsigned long id) {id_ = id;} + private: + #pragma db id auto access(id) + unsigned long id_; + }; + + #pragma db object + struct object2 + { + object2 (): id_ (0) {} + + public: + unsigned long id () const {return id_;} + unsigned long& id () {return id_;} + private: + #pragma db id auto access(id) + unsigned long id_; + }; + + #pragma db object + struct object3 + { + object3 (): id_ (0) {} + + #pragma db id auto + const unsigned long id_; + }; + + #pragma db value + struct uuid + { + uuid () {std::memset (data_, 0, sizeof (data_));} + explicit uuid (const char* d) {data (d);} + + public: + const char* data () const {return data_;} + void data (const char* d) {std::memcpy (data_, d, sizeof (data_));} + private: + #pragma db type(BINARY16_TYPE) column("") access(data) + char data_[16]; + }; + + #pragma db object + struct object4 + { + public: + const uuid& id () const {return id_;} + void id (const uuid& id) {id_ = id;} + private: + #pragma db id access(id) + uuid id_; + }; +} + +// Test version accessor/modifier functionality. +// +#pragma db namespace table("t6_") +namespace test6 +{ + #pragma db object optimistic + struct object1 + { + object1 (unsigned long id = 0): id_ (id), version_ (0) {} + + #pragma db id + unsigned long id_; + + public: + unsigned long version () const {return version_;} + void version (unsigned long version) {version_ = version;} + private: + #pragma db version access(version) + unsigned long version_; + }; + + #pragma db object optimistic + struct object2 + { + object2 (): version_ (0) {} + + #pragma db id auto + unsigned long id_; + + public: + unsigned long version () const {return version_;} + unsigned long& version () {return version_;} + private: + #pragma db version access(version) + unsigned long version_; + }; + + #pragma db object optimistic + struct object3 + { + object3 (unsigned long id = 0): id_ (id), version_ (0) {} + + #pragma db id + unsigned long id_; + + #pragma db version + const unsigned long version_; + }; +} + +// Test automatic discovery of accessor/modifier functions. +// +#pragma db namespace table("t7_") +namespace test7 +{ + #pragma db object + struct object + { + object () {} + object (unsigned long id): id_ (id) {} + + #pragma db id + unsigned long id_; + + public: + int i1 () const {return i1_;} + int& i1 () {return i1_;} + private: + int i1_; + + public: + const int& get_i2 () const {return i2_;} + void set_i2 (int i2) {i2_ = i2;} + private: + int i2_; + + public: + const int& getI3 () const {return i3_;} + void setI3 (const int& i3) {i3_ = i3;} + private: + int i3_; + + public: + int geti4 () const {return i4;} + int seti4 (int v) {int r (i4); i4 = v; return r;} + private: + int i4; + + // Prefer reference modifier. + // + public: + int i5 () const {return i5_;} + int& i5 () {return i5_;} + void i5 (int i5); + private: + int i5_; + + // Prefer reference modifier (reverse function order). + // + public: + int i6 () const {return i6_;} + void i6 (int i6); + int& i6 () {return i6_;} + private: + int i6_; + + // Custom accessor/modifier regex. + // + public: + int GetI7 () const {return i7_;} + void SetI7 (int i7) {i7_ = i7;} + private: + int i7_; + + // Array member via ref. + // + public: + const char* b1 () const {return b1_;} + char* b1 () {return b1_;} + private: + #pragma db type(BINARY16_TYPE) + char b1_[16]; + + // Array member via modifier. + // + public: + const char* b2 () const {return b2_;} + void b2 (const char* b2) {std::memcpy (b2_, b2, sizeof (b2_));} + private: + #pragma db type(BINARY16_TYPE) + char b2_[16]; + + public: + bool operator== (const object& o) const + { + return id_ == o.id_ && + i1_ == o.i1_ && + i2_ == o.i2_ && + i3_ == o.i3_ && + i4 == o.i4 && + i5_ == o.i5_ && + i6_ == o.i6_ && + i7_ == o.i7_ && + std::memcmp (b1_, o.b1_, sizeof (b1_)) == 0 && + std::memcmp (b2_, o.b2_, sizeof (b2_)) == 0; + } + }; +} + +#endif // TEST_HXX diff --git a/odb-tests/common/access/testscript b/odb-tests/common/access/testscript new file mode 100644 index 0000000..04f0ec0 --- /dev/null +++ b/odb-tests/common/access/testscript @@ -0,0 +1,33 @@ +# file : common/access/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; + $* +} |