FMDatabaseQueueTests.m 5.0 KB

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