CarbStoreHKQueryTests.swift 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //
  2. // CarbStoreHKQueryTests.swift
  3. // LoopKitHostedTests
  4. //
  5. // Created by Darin Krauss on 10/9/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import XCTest
  9. import HealthKit
  10. @testable import LoopKit
  11. class CarbStoreHKQueryTests: PersistenceControllerTestCase {
  12. var healthStore: HKHealthStoreMock!
  13. var carbStore: CarbStore!
  14. override func setUp() {
  15. super.setUp()
  16. healthStore = HKHealthStoreMock()
  17. carbStore = CarbStore(healthStore: healthStore,
  18. cacheStore: cacheStore,
  19. cacheLength: .hours(24),
  20. defaultAbsorptionTimes: (fast: .minutes(30), medium: .hours(3), slow: .hours(5)),
  21. observationInterval: .hours(1),
  22. provenanceIdentifier: Bundle.main.bundleIdentifier!)
  23. let semaphore = DispatchSemaphore(value: 0)
  24. cacheStore.onReady { (error) in
  25. semaphore.signal()
  26. }
  27. semaphore.wait()
  28. }
  29. override func tearDown() {
  30. carbStore = nil
  31. healthStore = nil
  32. super.tearDown()
  33. }
  34. func testHKQueryAnchorPersistence() {
  35. var observerQuery: HKObserverQueryMock? = nil
  36. var anchoredObjectQuery: HKAnchoredObjectQueryMock? = nil
  37. carbStore.createObserverQuery = { (sampleType, predicate, updateHandler) -> HKObserverQuery in
  38. observerQuery = HKObserverQueryMock(sampleType: sampleType, predicate: predicate, updateHandler: updateHandler)
  39. return observerQuery!
  40. }
  41. let authorizationCompletion = expectation(description: "authorization completion")
  42. carbStore.authorize { (result) in
  43. print(result)
  44. authorizationCompletion.fulfill()
  45. }
  46. waitForExpectations(timeout: 3)
  47. XCTAssertNotNil(observerQuery)
  48. let anchoredObjectQueryCreationExpectation = expectation(description: "anchored object query creation")
  49. carbStore.createAnchoredObjectQuery = { (sampleType, predicate, anchor, limit, resultsHandler) -> HKAnchoredObjectQuery in
  50. anchoredObjectQuery = HKAnchoredObjectQueryMock(type: sampleType, predicate: predicate, anchor: anchor, limit: limit, resultsHandler: resultsHandler)
  51. anchoredObjectQueryCreationExpectation.fulfill()
  52. return anchoredObjectQuery!
  53. }
  54. let observerQueryCompletionExpectation = expectation(description: "observer query completion")
  55. let observerQueryCompletionHandler = {
  56. observerQueryCompletionExpectation.fulfill()
  57. }
  58. // This simulates a signal marking the arrival of new HK Data.
  59. observerQuery!.updateHandler(observerQuery!, observerQueryCompletionHandler, nil)
  60. wait(for: [anchoredObjectQueryCreationExpectation], timeout: 3)
  61. // Trigger results handler for anchored object query
  62. let returnedAnchor = HKQueryAnchor(fromValue: 5)
  63. anchoredObjectQuery!.resultsHandler(anchoredObjectQuery!, [], [], returnedAnchor, nil)
  64. // Wait for observerQueryCompletionExpectation
  65. waitForExpectations(timeout: 3)
  66. XCTAssertNotNil(carbStore.queryAnchor)
  67. cacheStore.managedObjectContext.performAndWait {}
  68. // Create a new carb store, and ensure it uses the last query anchor
  69. let newCarbStore = CarbStore(healthStore: healthStore,
  70. cacheStore: cacheStore,
  71. cacheLength: .hours(24),
  72. defaultAbsorptionTimes: (fast: .minutes(30), medium: .hours(3), slow: .hours(5)),
  73. observationInterval: .hours(1),
  74. provenanceIdentifier: Bundle.main.bundleIdentifier!)
  75. let newAuthorizationCompletion = expectation(description: "authorization completion")
  76. observerQuery = nil
  77. newCarbStore.createObserverQuery = { (sampleType, predicate, updateHandler) -> HKObserverQuery in
  78. observerQuery = HKObserverQueryMock(sampleType: sampleType, predicate: predicate, updateHandler: updateHandler)
  79. return observerQuery!
  80. }
  81. newCarbStore.authorize { (result) in
  82. newAuthorizationCompletion.fulfill()
  83. }
  84. waitForExpectations(timeout: 3)
  85. anchoredObjectQuery = nil
  86. let newAnchoredObjectQueryCreationExpectation = expectation(description: "new anchored object query creation")
  87. newCarbStore.createAnchoredObjectQuery = { (sampleType, predicate, anchor, limit, resultsHandler) -> HKAnchoredObjectQuery in
  88. anchoredObjectQuery = HKAnchoredObjectQueryMock(type: sampleType, predicate: predicate, anchor: anchor, limit: limit, resultsHandler: resultsHandler)
  89. newAnchoredObjectQueryCreationExpectation.fulfill()
  90. return anchoredObjectQuery!
  91. }
  92. // This simulates a signal marking the arrival of new HK Data.
  93. observerQuery!.updateHandler(observerQuery!, {}, nil)
  94. wait(for: [newAnchoredObjectQueryCreationExpectation], timeout: 3)
  95. // Assert new carb store is querying with the last anchor that our HealthKit mock returned
  96. XCTAssertEqual(returnedAnchor, anchoredObjectQuery?.anchor)
  97. anchoredObjectQuery!.resultsHandler(anchoredObjectQuery!, [], [], returnedAnchor, nil)
  98. }
  99. }