1 package expo.modules.updates.db
2 
3 import android.content.Context
4 import androidx.room.Room
5 import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
6 import androidx.test.platform.app.InstrumentationRegistry
7 import expo.modules.updates.db.entity.UpdateEntity
8 import expo.modules.updates.db.enums.UpdateStatus
9 import expo.modules.updates.db.entity.AssetEntity
10 import io.mockk.every
11 import io.mockk.spyk
12 import org.json.JSONObject
13 import org.junit.After
14 import org.junit.Assert
15 import org.junit.Before
16 import org.junit.Test
17 import org.junit.runner.RunWith
18 import java.util.*
19 
20 @RunWith(AndroidJUnit4ClassRunner::class)
21 class DatabaseIntegrityCheckTest {
22   private lateinit var context: Context
23   private lateinit var db: UpdatesDatabase
24 
25   @Before
createDbnull26   fun createDb() {
27     context = InstrumentationRegistry.getInstrumentation().targetContext
28     db = Room.inMemoryDatabaseBuilder(context, UpdatesDatabase::class.java).build()
29   }
30 
31   @After
closeDbnull32   fun closeDb() {
33     db.close()
34   }
35 
36   @Test
testFilterEmbeddedUpdatesnull37   fun testFilterEmbeddedUpdates() {
38     // We can't run any updates with the status EMBEDDED if they aren't the update that's
39     // currently embedded in the installed app; the integrity check should remove any such updates
40     // from the database entirely.
41     val scopeKey = "testScopeKey"
42 
43     val embeddedUpdate1 = UpdateEntity(UUID.randomUUID(), Date(1608667857774L), "1.0", scopeKey, JSONObject("{}"))
44     embeddedUpdate1.status = UpdateStatus.EMBEDDED
45 
46     val embeddedUpdate2 = UpdateEntity(UUID.randomUUID(), Date(1608667857775L), "1.0", scopeKey, JSONObject("{}"))
47     embeddedUpdate2.status = UpdateStatus.EMBEDDED
48 
49     db.updateDao().insertUpdate(embeddedUpdate1)
50     db.updateDao().insertUpdate(embeddedUpdate2)
51 
52     Assert.assertEquals(2, db.updateDao().loadAllUpdates().size.toLong())
53 
54     DatabaseIntegrityCheck().run(db, null, embeddedUpdate2)
55 
56     val allUpdates = db.updateDao().loadAllUpdates()
57     Assert.assertEquals(1, allUpdates.size.toLong())
58     Assert.assertEquals(embeddedUpdate2.id, allUpdates[0].id)
59 
60     // cleanup
61     db.updateDao().deleteUpdates(allUpdates)
62   }
63 
64   @Test
testMissingAssetsnull65   fun testMissingAssets() {
66     val asset1 = AssetEntity("asset1", "png")
67     asset1.relativePath = "asset1.png"
68 
69     val scopeKey = "testScopeKey"
70 
71     val update1 = UpdateEntity(UUID.randomUUID(), Date(), "1.0", scopeKey, JSONObject("{}"))
72     update1.status = UpdateStatus.READY
73 
74     db.updateDao().insertUpdate(update1)
75     db.assetDao().insertAssets(listOf(asset1), update1)
76 
77     Assert.assertEquals(1, db.updateDao().loadAllUpdates().size.toLong())
78     Assert.assertEquals(1, db.assetDao().loadAllAssets().size.toLong())
79 
80     val integrityCheck = spyk(DatabaseIntegrityCheck())
81     every { integrityCheck.assetExists(any(), any()) } returns false
82     integrityCheck.run(db, context.cacheDir, update1)
83 
84     val allUpdates = db.updateDao().loadAllUpdates()
85     val allAssets = db.assetDao().loadAllAssets()
86     Assert.assertEquals(1, allUpdates.size.toLong())
87     Assert.assertEquals(UpdateStatus.PENDING, allUpdates[0].status)
88     Assert.assertEquals(1, allAssets.size.toLong())
89 
90     // cleanup
91     db.updateDao().deleteUpdates(allUpdates)
92   }
93 
94   @Test
testNoMissingAssetsnull95   fun testNoMissingAssets() {
96     val asset1 = AssetEntity("asset1", "png")
97     asset1.relativePath = "asset1.png"
98 
99     val scopeKey = "testScopeKey"
100 
101     val update1 = UpdateEntity(UUID.randomUUID(), Date(), "1.0", scopeKey, JSONObject("{}"))
102     update1.status = UpdateStatus.READY
103 
104     db.updateDao().insertUpdate(update1)
105     db.assetDao().insertAssets(listOf(asset1), update1)
106 
107     Assert.assertEquals(1, db.updateDao().loadAllUpdates().size.toLong())
108     Assert.assertEquals(1, db.assetDao().loadAllAssets().size.toLong())
109 
110     val integrityCheck = spyk(DatabaseIntegrityCheck())
111     every { integrityCheck.assetExists(any(), any()) } returns true
112     integrityCheck.run(db, context.cacheDir, update1)
113 
114     val allUpdates = db.updateDao().loadAllUpdates()
115     val allAssets = db.assetDao().loadAllAssets()
116     Assert.assertEquals(1, allUpdates.size.toLong())
117     Assert.assertEquals(UpdateStatus.READY, allUpdates[0].status)
118     Assert.assertEquals(1, allAssets.size.toLong())
119 
120     // cleanup
121     db.updateDao().deleteUpdates(allUpdates)
122   }
123 }
124