ClassInstances.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. //
  2. // Copyright (c) 2009 Brandon Jones
  3. //
  4. // This software is provided 'as-is', without any express or implied
  5. // warranty. In no event will the authors be held liable for any damages
  6. // arising from the use of this software.
  7. //
  8. // Permission is granted to anyone to use this software for any purpose,
  9. // including commercial applications, and to alter it and redistribute it
  10. // freely, subject to the following restrictions:
  11. //
  12. // 1. The origin of this software must not be misrepresented; you must not
  13. // claim that you wrote the original software. If you use this software
  14. // in a product, an acknowledgment in the product documentation would be
  15. // appreciated but is not required.
  16. //
  17. // 2. Altered source versions must be plainly marked as such, and must not be
  18. // misrepresented as being the original software.
  19. //
  20. // 3. This notice may not be removed or altered from any source
  21. // distribution.
  22. //
  23. #include <iostream>
  24. #include <gtest/gtest.h>
  25. #include <sqrat.h>
  26. #include "Fixture.h"
  27. using namespace Sqrat;
  28. class EmployeeName {
  29. public:
  30. const SQChar * firstName;
  31. const SQChar * lastName;
  32. };
  33. TEST_F(SqratTest, CharPtrBindingtoString) {
  34. DefaultVM::Set(vm);
  35. Class<EmployeeName> name(vm, _SC("EmployeeName"));
  36. name.Var(_SC("firstName"), &EmployeeName::firstName)
  37. .Var(_SC("lastName"), &EmployeeName::lastName);
  38. RootTable().Bind(_SC("EmployeeName"), name);
  39. Script script;
  40. script.CompileString(_SC(" \
  41. steve <- EmployeeName(); \
  42. steve.lastName = \"Jones\"; \
  43. \
  44. gTest.EXPECT_STR_EQ(steve.lastName, \"Jones\"); \
  45. "));
  46. if (Sqrat::Error::Occurred(vm)) {
  47. FAIL() << _SC("Compile Failed: ") << Sqrat::Error::Message(vm);
  48. }
  49. script.Run();
  50. if (Sqrat::Error::Occurred(vm)) {
  51. FAIL() << _SC("Run Failed: ") << Sqrat::Error::Message(vm);
  52. }
  53. }
  54. class Employee {
  55. public:
  56. Employee() : supervisor(NULL) {}
  57. Employee(const Employee& e) :
  58. firstName(e.firstName), lastName(e.lastName),
  59. age(e.age), department(e.department),
  60. wage(e.wage), supervisor(e.supervisor) {
  61. }
  62. void GiveRaise(float percent) {
  63. wage += (wage * percent);
  64. }
  65. const string ToString() const {
  66. std::basic_stringstream<SQChar> out;
  67. out << _SC("Employee: ") << lastName << _SC(", ") << firstName << _SC("\n");
  68. out << _SC("Age: ") << age << _SC("\n");
  69. out << _SC("Department: ") << department << _SC("\n");
  70. out << _SC("Hourly Wage: ") << wage << _SC("\n");
  71. if(supervisor != NULL) {
  72. out << _SC("Supervisor: ") << supervisor->lastName << _SC(", ") << supervisor->firstName << _SC("\n");
  73. }
  74. return out.str();
  75. }
  76. string firstName;
  77. string lastName;
  78. int age;
  79. string department;
  80. float wage;
  81. const SQChar * middleName;
  82. const SQChar * gender;
  83. Employee* supervisor;
  84. static string sharedData;
  85. };
  86. string Employee::sharedData;
  87. TEST_F(SqratTest, ClassInstances) {
  88. DefaultVM::Set(vm);
  89. Class<Employee> employee(vm, _SC("Employee"));
  90. employee
  91. .Var(_SC("firstName"), &Employee::firstName)
  92. .Var(_SC("lastName"), &Employee::lastName)
  93. .Var(_SC("age"), &Employee::age)
  94. .Var(_SC("department"), &Employee::department)
  95. .Var(_SC("wage"), &Employee::wage)
  96. .Var(_SC("supervisor"), &Employee::supervisor)
  97. .Var(_SC("middleName"), &Employee::middleName)
  98. .Var(_SC("gender"), &Employee::gender)
  99. .StaticVar(_SC("sharedData"), &Employee::sharedData)
  100. .Func(_SC("GiveRaise"), &Employee::GiveRaise)
  101. .Func(_SC("_tostring"), &Employee::ToString)
  102. ;
  103. // Bind the class to the root table
  104. RootTable().Bind(_SC("Employee"), employee);
  105. // Create an employee and set it as an instance in the script
  106. Employee bob;
  107. bob.firstName = _SC("Bob");
  108. bob.lastName = _SC("Smith");
  109. bob.age = 42;
  110. bob.department = _SC("Accounting");
  111. bob.wage = 21.95f;
  112. bob.gender = _SC("Male");
  113. bob.middleName = _SC("A");
  114. bob.sharedData = _SC("1234");
  115. RootTable().SetInstance(_SC("bob"), &bob);
  116. Script script;
  117. script.CompileString(_SC(" \
  118. steve <- Employee(); \
  119. steve.firstName = \"Steve\"; \
  120. steve.lastName = \"Jones\"; \
  121. steve.age = 34; \
  122. steve.wage = 35.00; \
  123. steve.department = \"Management\"; \
  124. steve.gender = \"male\"; \
  125. steve.middleName = \"B\"; \
  126. \
  127. gTest.EXPECT_INT_EQ(steve.age, 34); \
  128. gTest.EXPECT_FLOAT_EQ(steve.wage, 35.00); \
  129. gTest.EXPECT_STR_EQ(steve.lastName, \"Jones\"); \
  130. gTest.EXPECT_STR_EQ(steve.middleName, \"B\"); \
  131. gTest.EXPECT_STR_EQ(steve.gender, \"male\"); \
  132. \
  133. \
  134. bob.age += 1; \
  135. bob.GiveRaise(0.02); \
  136. bob.supervisor = steve; \
  137. \
  138. gTest.EXPECT_INT_EQ(bob.age, 43); \
  139. gTest.EXPECT_FLOAT_EQ(bob.wage, 22.389); \
  140. gTest.EXPECT_STR_EQ(bob.lastName, \"Smith\"); \
  141. gTest.EXPECT_STR_EQ(bob.middleName, \"A\"); \
  142. gTest.EXPECT_STR_EQ(bob.gender, \"Male\"); \
  143. gTest.EXPECT_STR_EQ(bob.sharedData, \"1234\"); \
  144. \
  145. // Uncomment the following to see _tostring demonstrated \
  146. //::print(steve); \
  147. //::print(\"===========\\n\"); \
  148. //::print(bob); \
  149. "));
  150. if (Sqrat::Error::Occurred(vm)) {
  151. FAIL() << _SC("Compile Failed: ") << Sqrat::Error::Message(vm);
  152. }
  153. script.Run();
  154. if (Sqrat::Error::Occurred(vm)) {
  155. FAIL() << _SC("Run Failed: ") << Sqrat::Error::Message(vm);
  156. }
  157. // Since he was set as an instance, changes to Bob in the script carry through to the native object
  158. EXPECT_EQ(bob.age, 43);
  159. EXPECT_FLOAT_EQ(bob.wage, 22.389f);
  160. // Steve can also be retreived from the script as an employee:
  161. Object steveObj = RootTable().GetSlot(_SC("steve"));
  162. ASSERT_FALSE(steveObj.IsNull());
  163. Employee* steve = steveObj.Cast<Employee*>();
  164. ASSERT_FALSE(steve == NULL);
  165. EXPECT_EQ(steve->age, 34);
  166. EXPECT_FLOAT_EQ(steve->wage, 35.00f);
  167. }
  168. class B
  169. {
  170. private:
  171. int value;
  172. public:
  173. B(): value(-1) {}
  174. int set(int v)
  175. {
  176. return value = v;
  177. }
  178. int get()
  179. {
  180. //std::cout << "B's address is " << (long) this << std::endl;
  181. return value;
  182. }
  183. B& getB()
  184. {
  185. return *this;
  186. }
  187. B& getB2(int, char *)
  188. {
  189. return *this;
  190. }
  191. B& getB4( const B, B *, const B, int)
  192. {
  193. return *this;
  194. }
  195. B* getBPtr()
  196. {
  197. return this;
  198. }
  199. static string shared;
  200. static int sharedInt;
  201. };
  202. string B::shared ;
  203. int B::sharedInt = -1;
  204. TEST_F(SqratTest, InstanceReferencesAndStaticMembers) {
  205. DefaultVM::Set(vm);
  206. Class<B> _B(vm, _SC("B"));
  207. _B
  208. .Func(_SC("set"), &B::set)
  209. .Func(_SC("get"), &B::get)
  210. .Func(_SC("getB"), &B::getB)
  211. .Func(_SC("getB2"), &B::getB2)
  212. .Func(_SC("getB4"), &B::getB4)
  213. .Func(_SC("getBPtr"), &B::getBPtr)
  214. .StaticVar(_SC("shared"), &B::shared)
  215. .StaticVar(_SC("sharedInt"), &B::sharedInt);
  216. RootTable().Bind(_SC("B"), _B);
  217. Script script;
  218. script.CompileString(_SC(" \
  219. b <- B();\
  220. bb <- B(); \
  221. \
  222. gTest.EXPECT_INT_EQ(b.get(), -1); \
  223. gTest.EXPECT_INT_EQ(bb.sharedInt, -1); \
  224. gTest.EXPECT_INT_EQ(b.sharedInt, -1); \
  225. b.set(12);\
  226. b.shared = \"a long string\"; \
  227. b.sharedInt = 1234; \
  228. gTest.EXPECT_STR_EQ(bb.shared, \"a long string\"); \
  229. gTest.EXPECT_STR_EQ(b.shared, \"a long string\"); \
  230. gTest.EXPECT_INT_EQ(bb.sharedInt, 1234); \
  231. gTest.EXPECT_INT_EQ(b.get(), 12); \
  232. local b1 = b.getBPtr();\
  233. b.set(20);\
  234. gTest.EXPECT_INT_EQ(b1.get(), 20); \
  235. local b2 = b.getB();\
  236. b.set(40);\
  237. gTest.EXPECT_INT_EQ(b1.get(), 40); \
  238. gTest.EXPECT_INT_EQ(b2.get(), 40); \
  239. local b3 = b.getB2(12, \"test\");\
  240. b.set(60);\
  241. gTest.EXPECT_INT_EQ(b2.get(), 60); \
  242. gTest.EXPECT_INT_EQ(b3.get(), 60); \
  243. local b4 = b.getB4(b, b, b, 33);\
  244. b.set(80);\
  245. gTest.EXPECT_INT_EQ(b3.get(), 80); \
  246. gTest.EXPECT_INT_EQ(b4.get(), 80); \
  247. \
  248. bb.shared = \"short str\"; \
  249. gTest.EXPECT_STR_EQ(b2.shared, \"short str\"); \
  250. gTest.EXPECT_STR_EQ(b3.shared, \"short str\"); \
  251. gTest.EXPECT_STR_EQ(b.shared, \"short str\"); \
  252. gTest.EXPECT_STR_EQ(b1.shared, \"short str\"); \
  253. gTest.EXPECT_STR_EQ(b4.shared, \"short str\"); \
  254. gTest.EXPECT_INT_EQ(b.sharedInt, 1234); \
  255. gTest.EXPECT_INT_EQ(b1.sharedInt, 1234); \
  256. gTest.EXPECT_INT_EQ(b2.sharedInt, 1234); \
  257. gTest.EXPECT_INT_EQ(b3.sharedInt, 1234); \
  258. gTest.EXPECT_INT_EQ(b4.sharedInt, 1234); \
  259. b4.shared = \"abcde\"; \
  260. b4.sharedInt = 9999; \
  261. gTest.EXPECT_STR_EQ(bb.shared, \"abcde\"); \
  262. gTest.EXPECT_INT_EQ(bb.sharedInt, 9999); \
  263. gTest.EXPECT_INT_EQ(b1.sharedInt, 9999); \
  264. "));
  265. if (Sqrat::Error::Occurred(vm)) {
  266. FAIL() << _SC("Compile Failed: ") << Sqrat::Error::Message(vm);
  267. }
  268. script.Run();
  269. if (Sqrat::Error::Occurred(vm)) {
  270. FAIL() << _SC("Run Failed: ") << Sqrat::Error::Message(vm);
  271. }
  272. }
  273. class A
  274. {
  275. protected:
  276. int v;
  277. public:
  278. A(): v(-1) {}
  279. int getv()
  280. {
  281. return v;
  282. }
  283. };
  284. class AA: public A
  285. {
  286. public:
  287. int setv(int v_)
  288. {
  289. return v = v_;
  290. }
  291. };
  292. class AAA: public AA
  293. {
  294. };
  295. class AB: public A, public B
  296. {
  297. };
  298. class BB: public B
  299. {
  300. };
  301. int abc(A & a, AA & aa, AB *ab)
  302. {
  303. aa.setv(12);
  304. ab->set(34);
  305. return a.getv();
  306. }
  307. class W
  308. {
  309. public:
  310. void f1(A &a) {}
  311. void f2(A * a) {}
  312. void f3(AAA aaa)
  313. {
  314. }
  315. void f4(const AB ab) {}
  316. int abc(A * a, AA & aa, B *b)
  317. {
  318. aa.setv(12);
  319. b->set(34);
  320. return a->getv();
  321. }
  322. };
  323. TEST_F(SqratTest, SimpleTypeChecking) {
  324. DefaultVM::Set(vm);
  325. Class<B> _B(vm, _SC("B"));
  326. _B
  327. .Func(_SC("set"), &B::set)
  328. .Func(_SC("get"), &B::get)
  329. .Func(_SC("getB"), &B::getB)
  330. .Func(_SC("getBPtr"), &B::getBPtr);
  331. RootTable().Bind(_SC("B"), _B);
  332. DerivedClass<BB, B> _BB(vm, _SC("BB"));
  333. RootTable().Bind(_SC("BB"), _BB);
  334. Class<A> _A(vm, _SC("A"));
  335. RootTable().Bind(_SC("A"), _A);
  336. DerivedClass<AA, A> _AA(vm, _SC("AA"));
  337. RootTable().Bind(_SC("AA"), _AA);
  338. DerivedClass<AAA, A> _AAA(vm, _SC("AAA"));
  339. RootTable().Bind(_SC("AAA"), _AAA);
  340. DerivedClass<AB, B> _AB(vm, _SC("AB"));
  341. RootTable().Bind(_SC("AB"), _AB);
  342. Class<W> _W(vm, _SC("W"));
  343. _W.Func(_SC("f1"), &W::f1);
  344. _W.Func(_SC("f2"), &W::f2);
  345. _W.Func(_SC("f3"), &W::f3);
  346. _W.Func(_SC("f4"), &W::f4);
  347. _W.Func(_SC("abc"), &W::abc);
  348. RootTable().Bind(_SC("W"), _W);
  349. RootTable().Func(_SC("abc"), &abc);
  350. Script script;
  351. script.CompileString(_SC(" \
  352. b <- B();\
  353. bb <- BB(); \
  354. a <- A(); \
  355. aa <- AA(); \
  356. aaa <- AAA(); \
  357. ab <- AB(); \
  358. abc(a, aa, ab); \
  359. w <- W(); \
  360. w.f1(a); \
  361. w.f1(aaa); \
  362. w.f2(a); \
  363. w.f3(aaa); \
  364. w.f4(ab); \
  365. w.abc(aaa, aa, bb); \
  366. w.abc(aa, aa, b); \
  367. \
  368. local raised = false;\
  369. try { \
  370. w.f1(b);\
  371. gTest.EXPECT_INT_EQ(0, 1); \
  372. }\
  373. catch (ex) {\
  374. raised = true;\
  375. print(ex + \"\\n\"); \
  376. }\
  377. gTest.EXPECT_TRUE(raised); \
  378. \
  379. raised = false;\
  380. try { \
  381. w.abc(aa, a, ab); \
  382. gTest.EXPECT_INT_EQ(0, 1); \
  383. }\
  384. catch (ex) {\
  385. raised = true;\
  386. print(ex + \"\\n\"); \
  387. }\
  388. gTest.EXPECT_TRUE(raised); \
  389. \
  390. \
  391. raised = false;\
  392. try { \
  393. w.f3(a); \
  394. gTest.EXPECT_INT_EQ(0, 1); \
  395. }\
  396. catch (ex) {\
  397. raised = true;\
  398. print(ex + \"\\n\"); \
  399. }\
  400. gTest.EXPECT_TRUE(raised); \
  401. \
  402. \
  403. raised = false;\
  404. try { \
  405. w.abc(a, aa); \
  406. gTest.EXPECT_INT_EQ(0, 1); \
  407. }\
  408. catch (ex) {\
  409. raised = true;\
  410. print(ex + \"\\n\"); \
  411. }\
  412. gTest.EXPECT_TRUE(raised); \
  413. \
  414. raised = false;\
  415. try { \
  416. w.f4(ab, b); \
  417. gTest.EXPECT_INT_EQ(0, 1); \
  418. }\
  419. catch (ex) {\
  420. raised = true;\
  421. print(ex + \"\\n\"); \
  422. }\
  423. gTest.EXPECT_TRUE(raised); \
  424. \
  425. "));
  426. if (Sqrat::Error::Occurred(vm)) {
  427. FAIL() << _SC("Compile Failed: ") << Sqrat::Error::Message(vm);
  428. }
  429. script.Run();
  430. if (Sqrat::Error::Occurred(vm)) {
  431. FAIL() << _SC("Run Failed: ") << Sqrat::Error::Message(vm);
  432. }
  433. }