1 //  Copyright (c) 2020 650 Industries, Inc. All rights reserved.
2 
3 import ExpoModulesTestCore
4 
5 @testable import EXUpdates
6 
7 import EXManifests
8 
9 class UpdatesDatabaseIntegrityCheckMockingAssetExists : UpdatesDatabaseIntegrityCheck {
assetExistsnull10   public override func assetExists(_ asset: UpdateAsset, inDirectory directory: URL) -> Bool {
11     return asset.key == "asset1"
12   }
13 }
14 
15 class UpdatesDatabaseIntegrityCheckSpec : ExpoSpec {
specnull16   override func spec() {
17     var testDatabaseDir: URL!
18     var db: UpdatesDatabase!
19 
20     beforeEach {
21       let applicationSupportDir = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).last
22       testDatabaseDir = applicationSupportDir!.appendingPathComponent("UpdatesDatabaseTests")
23 
24       try? FileManager.default.removeItem(atPath: testDatabaseDir.path)
25 
26       if !FileManager.default.fileExists(atPath: testDatabaseDir.path) {
27         try! FileManager.default.createDirectory(atPath: testDatabaseDir.path, withIntermediateDirectories: true)
28       }
29 
30       db = UpdatesDatabase()
31       db.databaseQueue.sync {
32         try! db.openDatabase(inDirectory: testDatabaseDir)
33       }
34     }
35 
36     afterEach {
37       db.databaseQueue.sync {
38         db.closeDatabase()
39       }
40 
41       try! FileManager.default.removeItem(atPath: testDatabaseDir.path)
42     }
43 
44     describe("filter embedded updates") {
45       it("works") {
46         // We can't run any updates with the status EMBEDDED if they aren't the update that's
47         // currently embedded in the installed app; the integrity check should remove any such updates
48         // from the database entirely.
49 
50         let scopeKey = "testScopeKey"
51         let runtimeVersion = "1.0"
52         let config = UpdatesConfig.config(fromDictionary: [
53           UpdatesConfig.EXUpdatesConfigScopeKeyKey: scopeKey,
54           UpdatesConfig.EXUpdatesConfigRuntimeVersionKey: runtimeVersion
55         ])
56 
57         let update1 = Update(
58           manifest: ManifestFactory.manifest(forManifestJSON: [:]),
59           config: config,
60           database: db,
61           updateId: UUID(),
62           scopeKey: scopeKey,
63           commitTime: Date(timeIntervalSince1970: 1608667851),
64           runtimeVersion: runtimeVersion,
65           keep: true,
66           status: .StatusEmbedded,
67           isDevelopmentMode: false,
68           assetsFromManifest: []
69         )
70         let update2 = Update(
71           manifest: ManifestFactory.manifest(forManifestJSON: [:]),
72           config: config,
73           database: db,
74           updateId: UUID(),
75           scopeKey: scopeKey,
76           commitTime: Date(timeIntervalSince1970: 1608667852),
77           runtimeVersion: runtimeVersion,
78           keep: true,
79           status: .StatusEmbedded,
80           isDevelopmentMode: false,
81           assetsFromManifest: []
82         )
83 
84         db.databaseQueue.sync {
85           try! db.addUpdate(update1)
86           try! db.addUpdate(update2)
87 
88           expect(try! db.allUpdates(withConfig: config).count) == 2
89 
90           try! UpdatesDatabaseIntegrityCheck().run(withDatabase: db, directory: testDatabaseDir, config: config, embeddedUpdate: update2)
91 
92           let allUpdates = try! db.allUpdates(withConfig: config)
93           expect(allUpdates.count) == 1
94           expect(update2.updateId) == allUpdates.first?.updateId
95         }
96       }
97     }
98 
99     describe("missing assets") {
100       it("works") {
101         let asset1 = UpdateAsset(key: "asset1", type: "png")
102         asset1.downloadTime = Date()
103         asset1.contentHash = "hash1"
104         let asset2 = UpdateAsset(key: "asset2", type: "png")
105         asset2.downloadTime = Date()
106         asset2.contentHash = "hash2"
107 
108         let scopeKey = "testScopeKey"
109         let runtimeVersion = "1.0"
110         let config = UpdatesConfig.config(fromDictionary: [
111           UpdatesConfig.EXUpdatesConfigScopeKeyKey: scopeKey,
112           UpdatesConfig.EXUpdatesConfigRuntimeVersionKey: runtimeVersion
113         ])
114 
115         let update1 = Update(
116           manifest: ManifestFactory.manifest(forManifestJSON: [:]),
117           config: config,
118           database: db,
119           updateId: UUID(),
120           scopeKey: scopeKey,
121           commitTime: Date(timeIntervalSince1970: 1608667851),
122           runtimeVersion: runtimeVersion,
123           keep: true,
124           status: .StatusEmbedded,
125           isDevelopmentMode: false,
126           assetsFromManifest: []
127         )
128         let update2 = Update(
129           manifest: ManifestFactory.manifest(forManifestJSON: [:]),
130           config: config,
131           database: db,
132           updateId: UUID(),
133           scopeKey: scopeKey,
134           commitTime: Date(timeIntervalSince1970: 1608667852),
135           runtimeVersion: runtimeVersion,
136           keep: true,
137           status: .StatusEmbedded,
138           isDevelopmentMode: false,
139           assetsFromManifest: []
140         )
141 
142         db.databaseQueue.sync {
143           try! db.addUpdate(update1)
144           try! db.addUpdate(update2)
145           try! db.addNewAssets([asset1], toUpdateWithId: update1.updateId)
146           try! db.addNewAssets([asset2], toUpdateWithId: update2.updateId)
147 
148           expect(try! db.allUpdates(withConfig: config).count) == 2
149           expect(try! db.allAssets().count) == 2
150 
151           try! UpdatesDatabaseIntegrityCheckMockingAssetExists().run(
152             withDatabase: db,
153             directory: testDatabaseDir,
154             config: config,
155             embeddedUpdate: nil
156           )
157 
158           let allUpdates = try! db.allUpdates(withConfig: config)
159           let allAssets = try! db.allAssets()
160 
161           // this is broken?
162 //          expect(allUpdates.count) == 1
163 //          expect(allAssets.count) == 2
164 //
165 //          let sortedUpdates = allUpdates.sorted { l, r in
166 //            return l.commitTime < r.commitTime
167 //          }
168 //          expect(sortedUpdates[0].status) == UpdateStatus.StatusReady
169 //          expect(sortedUpdates[1].status) == UpdateStatus.StatusPending
170         }
171       }
172     }
173   }
174 }
175