/Tests/Unit/SQLiteDatabaseTest.m

https://gitlab.com/iranjith4/Parse-SDK-iOS-OSX · Objective C · 600 lines · 426 code · 86 blank · 88 comment · 3 complexity · b5fc4df248b4e6e741b7904a8562d45f MD5 · raw file

  1. /**
  2. * Copyright (c) 2015-present, Parse, LLC.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. */
  9. #import <Bolts/Bolts.h>
  10. #import "BFTask+Private.h"
  11. #import "PFFileManager.h"
  12. #import "PFSQLiteDatabase.h"
  13. #import "PFSQLiteDatabaseResult.h"
  14. #import "PFUnitTestCase.h"
  15. #import "Parse_Private.h"
  16. @interface SQLiteDatabaseTest : PFUnitTestCase {
  17. PFSQLiteDatabase *database;
  18. }
  19. @end
  20. @implementation SQLiteDatabaseTest
  21. ///--------------------------------------
  22. #pragma mark - Helpers
  23. ///--------------------------------------
  24. - (NSString *)databasePath {
  25. return [NSTemporaryDirectory() stringByAppendingPathComponent:@"test.db"];
  26. }
  27. ///--------------------------------------
  28. #pragma mark - XCTestCase
  29. ///--------------------------------------
  30. - (void)setUp {
  31. [super setUp];
  32. database = [PFSQLiteDatabase databaseWithPath:[self databasePath]];
  33. }
  34. - (void)tearDown {
  35. if (database != NULL) {
  36. [[[database isOpenAsync] continueWithBlock:^id(BFTask *task) {
  37. BOOL isOpen = [task.result boolValue];
  38. if (isOpen) {
  39. return [database closeAsync];
  40. }
  41. return task;
  42. }] waitUntilFinished];
  43. }
  44. // delete DB file;
  45. [[NSFileManager defaultManager] removeItemAtPath:[self databasePath] error:NULL];
  46. [super tearDown];
  47. }
  48. ///--------------------------------------
  49. #pragma mark - Helpers
  50. ///--------------------------------------
  51. // Should return BFTask to not waste `waitUntilFinished`
  52. - (BFTask *)createDatabaseAsync {
  53. // Drop existing database first if any.
  54. return [[[[database openAsync] continueWithBlock:^id(BFTask *task) {
  55. return [database executeSQLAsync:@"DROP TABLE test" withArgumentsInArray:nil];
  56. }] continueWithBlock:^id(BFTask *task) {
  57. return [database openAsync];
  58. }] continueWithBlock:^id(BFTask *task) {
  59. return [database executeSQLAsync:@"CREATE TABLE test (a text, b text, c integer, d double)"
  60. withArgumentsInArray:nil];
  61. }];
  62. }
  63. ///--------------------------------------
  64. #pragma mark - Tests
  65. ///--------------------------------------
  66. - (void)testOpen {
  67. [[[[[[[[[database openAsync] continueWithBlock:^id(BFTask *task) {
  68. return [database isOpenAsync];
  69. }] continueWithBlock:^id(BFTask *task) {
  70. XCTAssertTrue([task.result boolValue]);
  71. return [database openAsync];
  72. }] continueWithBlock:^id(BFTask *task) {
  73. // Should error because DB is opened
  74. XCTAssertNotNil(task.error);
  75. return [database closeAsync];
  76. }] continueWithBlock:^id(BFTask *task) {
  77. return [database isOpenAsync];
  78. }] continueWithBlock:^id(BFTask *task) {
  79. XCTAssertFalse([task.result boolValue]);
  80. return [database closeAsync];
  81. }] continueWithBlock:^id(BFTask *task) {
  82. XCTAssertNotNil(task.error);
  83. return [database openAsync];
  84. }] continueWithBlock:^id(BFTask *task) {
  85. // Should fail because database was closed already, and reopened.
  86. XCTAssertNotNil(task.error);
  87. return task;
  88. }] waitUntilFinished];
  89. }
  90. - (void)testCRUD {
  91. [[[[[[[[[[[[database openAsync] continueWithBlock:^id(BFTask *task) {
  92. return [database executeSQLAsync:@"CREATE TABLE test (a text, b text, c integer, d double)"
  93. withArgumentsInArray:nil];
  94. }] continueWithBlock:^id(BFTask *task) {
  95. // Make sure it success
  96. XCTAssertNil(task.error);
  97. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  98. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  99. }] continueWithBlock:^id(BFTask *task) {
  100. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  101. }] continueWithBlock:^id(BFTask *task) {
  102. PFSQLiteDatabaseResult *result = task.result;
  103. // Make sure first element exists
  104. XCTAssertTrue([result next]);
  105. // Check values
  106. XCTAssertEqualObjects(@"one", [result stringForColumnIndex:0]);
  107. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  108. XCTAssertEqual(3, [result intForColumnIndex:2]);
  109. // Make sure there's nothing more
  110. XCTAssertFalse([result next]);
  111. // Test the cached statement
  112. // TODO (hallucinogen): how can we be sure we're getting this from cached statement?
  113. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  114. }] continueWithBlock:^id(BFTask *task) {
  115. PFSQLiteDatabaseResult *result = task.result;
  116. // Make sure first element exists
  117. XCTAssertTrue([result next]);
  118. // Check values
  119. XCTAssertEqualObjects(@"one", [result stringForColumnIndex:0]);
  120. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  121. XCTAssertEqual(3, [result intForColumnIndex:2]);
  122. // Make sure there's nothing more
  123. XCTAssertFalse([result next]);
  124. return [database executeSQLAsync:@"UPDATE test SET a = ?, c = ? WHERE c = ?"
  125. withArgumentsInArray:[NSArray arrayWithObjects:@"onenew", @5, @3, nil]];
  126. }] continueWithBlock:^id(BFTask *task) {
  127. // Make sure there's nothing wrong
  128. XCTAssertNil(task.error);
  129. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  130. }] continueWithBlock:^id(BFTask *task) {
  131. PFSQLiteDatabaseResult *result = task.result;
  132. // Make sure first element exists
  133. XCTAssertTrue([result next]);
  134. // Check values
  135. XCTAssertEqualObjects(@"onenew", [result stringForColumnIndex:0]);
  136. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  137. XCTAssertEqual(5, [result intForColumnIndex:2]);
  138. // Make sure there's nothing more
  139. XCTAssertFalse([result next]);
  140. return [database executeSQLAsync:@"DELETE FROM test WHERE c = ?"
  141. withArgumentsInArray:[NSArray arrayWithObjects:@5, nil]];
  142. }] continueWithBlock:^id(BFTask *task) {
  143. // Make sure there's nothing wrong
  144. XCTAssertNil(task.error);
  145. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  146. }] continueWithBlock:^id(BFTask *task) {
  147. // Make sure there's nothing wrong
  148. XCTAssertNil(task.error);
  149. PFSQLiteDatabaseResult *result = task.result;
  150. // Make sure there's nothing more
  151. XCTAssertFalse(result.next);
  152. // Clean up
  153. return [database executeSQLAsync:@"DROP TABLE test" withArgumentsInArray:nil];
  154. }] continueWithBlock:^id(BFTask *task) {
  155. // Make sure there's nothing wrong
  156. XCTAssertNil(task.error);
  157. return task;
  158. }] waitUntilFinished];
  159. }
  160. // TODO (hallucinogen): this test consists of three units which can be separated.
  161. - (void)testTransaction {
  162. [[[[[[[[[[[[[[[[[self createDatabaseAsync] continueWithBlock:^id(BFTask *task) {
  163. return [database beginTransactionAsync];
  164. }] continueWithBlock:^id(BFTask *task) {
  165. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  166. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  167. }] continueWithBlock:^id(BFTask *task) {
  168. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  169. }] continueWithBlock:^id(BFTask *task) {
  170. PFSQLiteDatabaseResult *result = task.result;
  171. // Make sure first element exists
  172. XCTAssertTrue([result next]);
  173. // Check values
  174. XCTAssertEqualObjects(@"one", [result stringForColumnIndex:0]);
  175. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  176. XCTAssertEqual(3, [result intForColumnIndex:2]);
  177. // Make sure there's nothing more
  178. XCTAssertFalse(result.next);
  179. // Commit
  180. return [database commitAsync];
  181. }] continueWithBlock:^id(BFTask *task) {
  182. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  183. }] continueWithBlock:^id(BFTask *task) {
  184. PFSQLiteDatabaseResult *result = task.result;
  185. // Make sure first element exists
  186. XCTAssertTrue([result next]);
  187. // Check values
  188. XCTAssertEqualObjects(@"one", [result stringForColumnIndex:0]);
  189. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  190. XCTAssertEqual(3, [result intForColumnIndex:2]);
  191. // Make sure there's nothing more
  192. XCTAssertFalse(result.next);
  193. return [database beginTransactionAsync];
  194. }] continueWithBlock:^id(BFTask *task) {
  195. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  196. withArgumentsInArray:[NSArray arrayWithObjects:@"oneone", @"twotwo", @33, @44.44, nil]];
  197. }] continueWithBlock:^id(BFTask *task) {
  198. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  199. }] continueWithBlock:^id(BFTask *task) {
  200. // should have two results
  201. PFSQLiteDatabaseResult *result = task.result;
  202. // Make sure first element exists
  203. XCTAssertTrue([result next]);
  204. BOOL nextResult = [result next];
  205. // There's second element
  206. XCTAssertTrue(nextResult);
  207. nextResult = [result next];
  208. // There's nothing more
  209. XCTAssertFalse(nextResult);
  210. // Rollback
  211. return [database rollbackAsync];
  212. }] continueWithBlock:^id(BFTask *task) {
  213. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  214. }] continueWithBlock:^id(BFTask *task) {
  215. // Should have one result
  216. PFSQLiteDatabaseResult *result = task.result;
  217. // Make sure first element exists
  218. XCTAssertTrue([result next]);
  219. BOOL nextResult = [result next];
  220. // There's nothing more
  221. XCTAssertFalse(nextResult);
  222. // Now let's try making transaction, then close the database wbile it's in transaction
  223. return [database beginTransactionAsync];
  224. }] continueWithBlock:^id(BFTask *task) {
  225. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  226. withArgumentsInArray:[NSArray arrayWithObjects:@"oneone", @"twotwo", @33, @44.44, nil]];
  227. }] continueWithBlock:^id(BFTask *task) {
  228. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  229. }] continueWithBlock:^id(BFTask *task) {
  230. // Should have two results
  231. PFSQLiteDatabaseResult *result = task.result;
  232. // Make sure first element exists
  233. XCTAssertTrue([result next]);
  234. BOOL nextResult = [result next];
  235. XCTAssertTrue(nextResult);
  236. nextResult = [result next];
  237. XCTAssertFalse(nextResult);
  238. // Let's close the database while in transaction
  239. // The expected result: close successfully and the transaction would be rolled back
  240. return [database closeAsync];
  241. }] continueWithBlock:^id(BFTask *task) {
  242. XCTAssertNil(task.error);
  243. return [BFTask taskWithResult:nil];
  244. }] waitUntilFinished];
  245. database = [PFSQLiteDatabase databaseWithPath:[self databasePath]];
  246. [[[[[[[database openAsync] continueWithBlock:^id(BFTask *task) {
  247. XCTAssertNil(task.error);
  248. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  249. withArgumentsInArray:[NSArray arrayWithObjects:@"oneone", @"twotwo", @33, @44.44, nil]];
  250. }] continueWithBlock:^id(BFTask *task) {
  251. XCTAssertNil(task.error);
  252. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  253. }] continueWithBlock:^id(BFTask *task) {
  254. // Should have two results because the last one is rolled back
  255. PFSQLiteDatabaseResult *result = task.result;
  256. // Make sure first element exists
  257. XCTAssertTrue([result next]);
  258. BOOL nextResult = [result next];
  259. XCTAssertTrue(nextResult);
  260. nextResult = [result next];
  261. XCTAssertFalse(nextResult);
  262. // Try rolling back previous transaction (which should fail because the database has been
  263. // closed and currently there's no transaction)
  264. return [database rollbackAsync];
  265. }] continueWithBlock:^id(BFTask *task) {
  266. XCTAssertNotNil(task.error);
  267. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  268. }] continueWithBlock:^id(BFTask *task) {
  269. // Should still have two results
  270. PFSQLiteDatabaseResult *result = task.result;
  271. // Make sure first element exists
  272. XCTAssertTrue([result next]);
  273. BOOL nextResult = [result next];
  274. XCTAssertTrue(nextResult);
  275. nextResult = [result next];
  276. XCTAssertFalse(nextResult);
  277. return [database closeAsync];
  278. }] waitUntilFinished];
  279. }
  280. - (void)testOperationOnNonExistentTable {
  281. [[[[[[[self createDatabaseAsync] continueWithBlock:^id(BFTask *task) {
  282. return [database executeSQLAsync:@"INSERT INTO testFake (a, b, c, d) VALUES (?, ?, ?, ?)"
  283. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  284. }] continueWithBlock:^id(BFTask *task) {
  285. XCTAssertNotNil(task.error);
  286. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  287. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  288. }] continueWithBlock:^id(BFTask *task) {
  289. XCTAssertNil(task.error);
  290. return [database executeCachedQueryAsync:@"SELECT * FROM testFake" withArgumentsInArray:nil];
  291. }] continueWithBlock:^id(BFTask *task) {
  292. XCTAssertNotNil(task.error);
  293. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  294. }] continueWithBlock:^id(BFTask *task) {
  295. XCTAssertNil(task.error);
  296. // Should have one result
  297. PFSQLiteDatabaseResult *result = task.result;
  298. // Make sure first element exists
  299. XCTAssertTrue([result next]);
  300. BOOL nextResult = [result next];
  301. XCTAssertFalse(nextResult);
  302. // Clean up
  303. return [database closeAsync];
  304. }] waitUntilFinished];
  305. }
  306. - (void)testQuery {
  307. [[[[[[[[[self createDatabaseAsync] continueWithBlock:^id(BFTask *task) {
  308. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  309. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  310. }] continueWithBlock:^id(BFTask *task) {
  311. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  312. withArgumentsInArray:[NSArray arrayWithObjects:@"oneone", @"twotwo", @33, @44.44, nil]];
  313. }] continueWithBlock:^id(BFTask *task) {
  314. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  315. }] continueWithBlock:^id(BFTask *task) {
  316. // Should have two results
  317. PFSQLiteDatabaseResult *result = task.result;
  318. // Make sure first element exists
  319. XCTAssertTrue([result next]);
  320. BOOL nextResult = [result next];
  321. XCTAssertTrue(nextResult);
  322. nextResult = [result next];
  323. XCTAssertFalse(nextResult);
  324. return [database executeCachedQueryAsync:@"SELECT * FROM test WHERE c = ?"
  325. withArgumentsInArray:[NSArray arrayWithObjects:@3, nil]];
  326. }] continueWithBlock:^id(BFTask *task) {
  327. // Check result
  328. PFSQLiteDatabaseResult *result = task.result;
  329. // Make sure first element exists
  330. XCTAssertTrue([result next]);
  331. // Check values
  332. XCTAssertEqualObjects(@"one", [result stringForColumnIndex:0]);
  333. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  334. XCTAssertEqual(3, [result intForColumnIndex:2]);
  335. // Should have one result
  336. BOOL nextResult = [result next];
  337. XCTAssertFalse(nextResult);
  338. return [database executeSQLAsync:@"UPDATE test SET a = ?, c = ? WHERE c = ?"
  339. withArgumentsInArray:[NSArray arrayWithObjects:@"onenew", @5, @3, nil]];
  340. }] continueWithBlock:^id(BFTask *task) {
  341. return [database executeCachedQueryAsync:@"SELECT * FROM test WHERE c = ?"
  342. withArgumentsInArray:[NSArray arrayWithObjects:@5, nil]];
  343. }] continueWithBlock:^id(BFTask *task) {
  344. // Check result
  345. PFSQLiteDatabaseResult *result = task.result;
  346. // Make sure first element exists
  347. XCTAssertTrue([result next]);
  348. // Check values
  349. XCTAssertEqualObjects(@"onenew", [result stringForColumn:@"a"]);
  350. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  351. XCTAssertEqual(5, [result intForColumnIndex:2]);
  352. // Should have one result
  353. BOOL nextResult = [result next];
  354. XCTAssertFalse(nextResult);
  355. // Clean up
  356. return [database closeAsync];
  357. }] waitUntilFinished];
  358. }
  359. - (void)testCursorAndOperationOnDifferentThread {
  360. BFTask *taskWithCursor = [[[[[self createDatabaseAsync] continueWithBlock:^id(BFTask *task) {
  361. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  362. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  363. }] continueWithBlock:^id(BFTask *task) {
  364. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  365. withArgumentsInArray:[NSArray arrayWithObjects:@"oneone", @"twotwo", @33, @44.44, nil]];
  366. }] continueWithBlock:^id(BFTask *task) {
  367. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  368. }] continueWithExecutor:[BFExecutor defaultPriorityBackgroundExecutor] withBlock:^id(BFTask *task) {
  369. // Execute this in background
  370. PFSQLiteDatabaseResult *result = task.result;
  371. // Make sure first element exists
  372. XCTAssertTrue([result next]);
  373. // Check values
  374. XCTAssertEqualObjects(@"one", [result stringForColumnIndex:0]);
  375. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  376. XCTAssertEqual(3, [result intForColumnIndex:2]);
  377. return result;
  378. }];
  379. // Make sure we can read result from main thread
  380. [taskWithCursor waitUntilFinished];
  381. PFSQLiteDatabaseResult *result = taskWithCursor.result;
  382. // Try to access result in main thread
  383. XCTAssertEqualObjects(@"one", [result stringForColumnIndex:0]);
  384. XCTAssertEqualObjects(@"two", [result stringForColumnIndex:1]);
  385. XCTAssertEqual(3, [result intForColumnIndex:2]);
  386. XCTAssertTrue([result next]);
  387. XCTAssertEqualObjects(@"oneone", [result stringForColumnIndex:0]);
  388. XCTAssertEqualObjects(@"twotwo", [result stringForColumnIndex:1]);
  389. XCTAssertEqual(33, [result intForColumnIndex:2]);
  390. // Test clean up fail
  391. [[[[[[database executeSQLAsync:@"DROP TABLE test" withArgumentsInArray:nil] continueWithBlock:^id(BFTask *task) {
  392. XCTAssertNotNil(task.error);
  393. return task;
  394. }] continueWithExecutor:[BFExecutor defaultExecutor] withBlock:^id(BFTask *task) {
  395. // `result` should not increase
  396. XCTAssertFalse([result next]);
  397. return [database executeSQLAsync:@"DROP TABLE test" withArgumentsInArray:nil];
  398. }] continueWithBlock:^id(BFTask *task) {
  399. XCTAssertNil(task.error);
  400. return task;
  401. //return [database2 closeAsync];
  402. }] continueWithBlock:^id(BFTask *task) {
  403. XCTAssertNil(task.error);
  404. return [database closeAsync];
  405. }] waitUntilFinished];
  406. }
  407. - (void)testInvalidArgumentCount {
  408. [[[[self createDatabaseAsync] continueWithBlock:^id(BFTask *task) {
  409. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?)"
  410. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  411. }] continueWithBlock:^id(BFTask *task) {
  412. XCTAssertNotNil(task.error);
  413. XCTAssertEqual(PFSQLiteDatabaseInvalidArgumenCountErrorCode, [task.error.userInfo[@"code"] integerValue]);
  414. return [database closeAsync];
  415. }] waitUntilFinished];
  416. }
  417. - (void)testInvalidSQL {
  418. [[[[[self createDatabaseAsync] continueWithBlock:^id(BFTask *task) {
  419. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  420. withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", @3, @4.4, nil]];
  421. }] continueWithBlock:^id(BFTask *task) {
  422. return [database executeSQLAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  423. }] continueWithBlock:^id(BFTask *task) {
  424. XCTAssertNotNil(task.error);
  425. XCTAssertEqual(PFSQLiteDatabaseInvalidSQL, [task.error.userInfo[@"code"] integerValue]);
  426. return [database closeAsync];
  427. }] waitUntilFinished];
  428. }
  429. - (void)testColumnTypes {
  430. [[[[[self createDatabaseAsync] continueWithBlock:^id(BFTask *task) {
  431. return [database executeSQLAsync:@"INSERT INTO test (a, b, c, d) VALUES (?, ?, ?, ?)"
  432. withArgumentsInArray:@[ @1, [NSNull null], @"string", @13.37 ]];
  433. }] continueWithBlock:^id(BFTask *task) {
  434. return [database executeCachedQueryAsync:@"SELECT * FROM test" withArgumentsInArray:nil];
  435. }] continueWithBlock:^id(BFTask *task) {
  436. XCTAssertNil(task.error);
  437. PFSQLiteDatabaseResult *result = task.result;
  438. XCTAssertTrue([result next]);
  439. XCTAssertEqual([result intForColumn:@"a"], 1);
  440. XCTAssertEqual([result intForColumn:@"b"], 0);
  441. XCTAssertEqual([result intForColumn:@"c"], 0);
  442. XCTAssertEqual([result intForColumn:@"d"], 13);
  443. XCTAssertEqual([result intForColumnIndex:0], 1);
  444. XCTAssertEqual([result intForColumnIndex:1], 0);
  445. XCTAssertEqual([result intForColumnIndex:2], 0);
  446. XCTAssertEqual([result intForColumnIndex:3], 13);
  447. XCTAssertEqual([result longForColumn:@"a"], 1);
  448. XCTAssertEqual([result longForColumn:@"b"], 0);
  449. XCTAssertEqual([result longForColumn:@"c"], 0);
  450. XCTAssertEqual([result longForColumn:@"d"], 13);
  451. XCTAssertEqual([result longForColumnIndex:0], 1);
  452. XCTAssertEqual([result longForColumnIndex:1], 0);
  453. XCTAssertEqual([result longForColumnIndex:2], 0);
  454. XCTAssertEqual([result longForColumnIndex:3], 13);
  455. XCTAssertEqual([result boolForColumn:@"a"], YES);
  456. XCTAssertEqual([result boolForColumn:@"b"], NO);
  457. XCTAssertEqual([result boolForColumn:@"c"], NO);
  458. XCTAssertEqual([result boolForColumn:@"d"], YES);
  459. XCTAssertEqual([result boolForColumnIndex:0], YES);
  460. XCTAssertEqual([result boolForColumnIndex:1], NO);
  461. XCTAssertEqual([result boolForColumnIndex:2], NO);
  462. XCTAssertEqual([result boolForColumnIndex:3], YES);
  463. XCTAssertEqual([result doubleForColumn:@"a"], 1);
  464. XCTAssertEqual([result doubleForColumn:@"b"], 0);
  465. XCTAssertEqual([result doubleForColumn:@"c"], 0);
  466. XCTAssertEqual([result doubleForColumn:@"d"], 13.37);
  467. XCTAssertEqual([result doubleForColumnIndex:0], 1);
  468. XCTAssertEqual([result doubleForColumnIndex:1], 0);
  469. XCTAssertEqual([result doubleForColumnIndex:2], 0);
  470. XCTAssertEqual([result doubleForColumnIndex:3], 13.37);
  471. XCTAssertEqualObjects([result stringForColumn:@"a"], @"1");
  472. XCTAssertEqualObjects([result stringForColumn:@"b"], nil);
  473. XCTAssertEqualObjects([result stringForColumn:@"c"], @"string");
  474. XCTAssertEqualObjects([result stringForColumn:@"d"], @"13.37");
  475. XCTAssertEqualObjects([result stringForColumnIndex:0], @"1");
  476. XCTAssertEqualObjects([result stringForColumnIndex:1], nil);
  477. XCTAssertEqualObjects([result stringForColumnIndex:2], @"string");
  478. XCTAssertEqualObjects([result stringForColumnIndex:3], @"13.37");
  479. XCTAssertEqualObjects([result dateForColumn:@"a"], [NSDate dateWithTimeIntervalSince1970:1]);
  480. XCTAssertEqualObjects([result dateForColumn:@"b"], [NSDate dateWithTimeIntervalSince1970:0]);
  481. XCTAssertEqualObjects([result dateForColumn:@"c"], [NSDate dateWithTimeIntervalSince1970:0]);
  482. XCTAssertEqualObjects([result dateForColumn:@"d"], [NSDate dateWithTimeIntervalSince1970:13.37]);
  483. XCTAssertEqualObjects([result dateForColumnIndex:0], [NSDate dateWithTimeIntervalSince1970:1]);
  484. XCTAssertEqualObjects([result dateForColumnIndex:1], [NSDate dateWithTimeIntervalSince1970:0]);
  485. XCTAssertEqualObjects([result dateForColumnIndex:2], [NSDate dateWithTimeIntervalSince1970:0]);
  486. XCTAssertEqualObjects([result dateForColumnIndex:3], [NSDate dateWithTimeIntervalSince1970:13.37]);
  487. XCTAssertEqualObjects([result dataForColumn:@"a"], [NSData dataWithBytes:(char[]) { '1' } length:1]);
  488. XCTAssertEqualObjects([result dataForColumn:@"b"], nil);
  489. XCTAssertEqualObjects([result dataForColumn:@"c"], [NSData dataWithBytes:"string"length:6]);
  490. XCTAssertEqualObjects([result dataForColumn:@"d"], [NSData dataWithBytes:"13.37" length:5]);
  491. XCTAssertEqualObjects([result dataForColumnIndex:0], [NSData dataWithBytes:(char[]) { '1' } length:1]);
  492. XCTAssertEqualObjects([result dataForColumnIndex:1], nil);
  493. XCTAssertEqualObjects([result dataForColumnIndex:2], [NSData dataWithBytes:"string"length:6]);
  494. XCTAssertEqualObjects([result dataForColumnIndex:3], [NSData dataWithBytes:"13.37" length:5]);
  495. XCTAssertEqualObjects([result objectForColumn:@"a"], @"1");
  496. XCTAssertEqualObjects([result objectForColumn:@"b"], nil);
  497. XCTAssertEqualObjects([result objectForColumn:@"c"], @"string");
  498. XCTAssertEqualObjects([result objectForColumn:@"d"], @13.37);
  499. XCTAssertEqualObjects([result objectForColumnIndex:0], @"1");
  500. XCTAssertEqualObjects([result objectForColumnIndex:1], nil);
  501. XCTAssertEqualObjects([result objectForColumnIndex:2], @"string");
  502. XCTAssertEqualObjects([result objectForColumnIndex:3], @13.37);
  503. XCTAssertFalse([result columnIsNull:@"a"]);
  504. XCTAssertTrue([result columnIsNull:@"b"]);
  505. XCTAssertFalse([result columnIsNull:@"c"]);
  506. XCTAssertFalse([result columnIsNull:@"d"]);
  507. XCTAssertFalse([result columnIndexIsNull:0]);
  508. XCTAssertTrue([result columnIndexIsNull:1]);
  509. XCTAssertFalse([result columnIndexIsNull:2]);
  510. XCTAssertFalse([result columnIndexIsNull:3]);
  511. return [database closeAsync];
  512. }] waitUntilFinished];
  513. }
  514. @end