FMDatabaseQueueTests.m 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //
  2. // FMDatabaseQueueTests.m
  3. // fmdb
  4. //
  5. // Created by Graham Dennis on 24/11/2013.
  6. //
  7. //
  8. #import <XCTest/XCTest.h>
  9. #import "FMDatabaseQueue.h"
  10. #if FMDB_SQLITE_STANDALONE
  11. #import <sqlite3/sqlite3.h>
  12. #else
  13. #import <sqlite3.h>
  14. #endif
  15. @interface FMDatabaseQueueTests : FMDBTempDBTests
  16. @property FMDatabaseQueue *queue;
  17. @end
  18. @implementation FMDatabaseQueueTests
  19. + (void)populateDatabase:(FMDatabase *)db
  20. {
  21. [db executeUpdate:@"create table easy (a text)"];
  22. [db executeUpdate:@"create table qfoo (foo text)"];
  23. [db executeUpdate:@"insert into qfoo values ('hi')"];
  24. [db executeUpdate:@"insert into qfoo values ('hello')"];
  25. [db executeUpdate:@"insert into qfoo values ('not')"];
  26. }
  27. - (void)setUp
  28. {
  29. [super setUp];
  30. // Put setup code here. This method is called before the invocation of each test method in the class.
  31. self.queue = [FMDatabaseQueue databaseQueueWithPath:self.databasePath];
  32. }
  33. - (void)tearDown
  34. {
  35. // Put teardown code here. This method is called after the invocation of each test method in the class.
  36. [super tearDown];
  37. }
  38. - (void)testQueueSelect
  39. {
  40. [self.queue inDatabase:^(FMDatabase *adb) {
  41. int count = 0;
  42. FMResultSet *rsl = [adb executeQuery:@"select * from qfoo where foo like 'h%'"];
  43. while ([rsl next]) {
  44. count++;
  45. }
  46. XCTAssertEqual(count, 2);
  47. count = 0;
  48. rsl = [adb executeQuery:@"select * from qfoo where foo like ?", @"h%"];
  49. while ([rsl next]) {
  50. count++;
  51. }
  52. XCTAssertEqual(count, 2);
  53. }];
  54. }
  55. - (void)testReadOnlyQueue
  56. {
  57. FMDatabaseQueue *queue2 = [FMDatabaseQueue databaseQueueWithPath:self.databasePath flags:SQLITE_OPEN_READONLY];
  58. XCTAssertNotNil(queue2);
  59. {
  60. [queue2 inDatabase:^(FMDatabase *db2) {
  61. FMResultSet *rs1 = [db2 executeQuery:@"SELECT * FROM qfoo"];
  62. XCTAssertNotNil(rs1);
  63. [rs1 close];
  64. XCTAssertFalse(([db2 executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:3]]), @"Insert should fail because this is a read-only database");
  65. }];
  66. [queue2 close];
  67. // Check that when we re-open the database, it's still read-only
  68. [queue2 inDatabase:^(FMDatabase *db2) {
  69. FMResultSet *rs1 = [db2 executeQuery:@"SELECT * FROM qfoo"];
  70. XCTAssertNotNil(rs1);
  71. [rs1 close];
  72. XCTAssertFalse(([db2 executeUpdate:@"insert into easy values (?)", [NSNumber numberWithInt:3]]), @"Insert should fail because this is a read-only database");
  73. }];
  74. }
  75. }
  76. - (void)testStressTest
  77. {
  78. size_t ops = 16;
  79. dispatch_queue_t dqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  80. dispatch_apply(ops, dqueue, ^(size_t nby) {
  81. // just mix things up a bit for demonstration purposes.
  82. if (nby % 2 == 1) {
  83. [NSThread sleepForTimeInterval:.01];
  84. [self.queue inTransaction:^(FMDatabase *adb, BOOL *rollback) {
  85. FMResultSet *rsl = [adb executeQuery:@"select * from qfoo where foo like 'h%'"];
  86. while ([rsl next]) {
  87. ;// whatever.
  88. }
  89. }];
  90. }
  91. if (nby % 3 == 1) {
  92. [NSThread sleepForTimeInterval:.01];
  93. }
  94. [self.queue inTransaction:^(FMDatabase *adb, BOOL *rollback) {
  95. XCTAssertTrue([adb executeUpdate:@"insert into qfoo values ('1')"]);
  96. XCTAssertTrue([adb executeUpdate:@"insert into qfoo values ('2')"]);
  97. XCTAssertTrue([adb executeUpdate:@"insert into qfoo values ('3')"]);
  98. }];
  99. });
  100. [self.queue close];
  101. [self.queue inDatabase:^(FMDatabase *adb) {
  102. XCTAssertTrue([adb executeUpdate:@"insert into qfoo values ('1')"]);
  103. }];
  104. }
  105. - (void)testTransaction
  106. {
  107. [self.queue inDatabase:^(FMDatabase *adb) {
  108. [adb executeUpdate:@"create table transtest (a integer)"];
  109. XCTAssertTrue([adb executeUpdate:@"insert into transtest values (1)"]);
  110. XCTAssertTrue([adb executeUpdate:@"insert into transtest values (2)"]);
  111. int rowCount = 0;
  112. FMResultSet *ars = [adb executeQuery:@"select * from transtest"];
  113. while ([ars next]) {
  114. rowCount++;
  115. }
  116. XCTAssertEqual(rowCount, 2);
  117. }];
  118. [self.queue inTransaction:^(FMDatabase *adb, BOOL *rollback) {
  119. XCTAssertTrue([adb executeUpdate:@"insert into transtest values (3)"]);
  120. if (YES) {
  121. // uh oh!, something went wrong (not really, this is just a test
  122. *rollback = YES;
  123. return;
  124. }
  125. XCTFail(@"This shouldn't be reached");
  126. }];
  127. [self.queue inDatabase:^(FMDatabase *adb) {
  128. int rowCount = 0;
  129. FMResultSet *ars = [adb executeQuery:@"select * from transtest"];
  130. while ([ars next]) {
  131. rowCount++;
  132. }
  133. XCTAssertFalse([adb hasOpenResultSets]);
  134. XCTAssertEqual(rowCount, 2);
  135. }];
  136. }
  137. @end