Skip to content
Snippets Groups Projects
Commit faaa7a6d authored by Koen's avatar Koen
Browse files

Fixes to properly handle deletions.

parent 839e4c4a
No related branches found
No related tags found
No related merge requests found
...@@ -56,6 +56,20 @@ ...@@ -56,6 +56,20 @@
</AndroidTestResultsTableState> </AndroidTestResultsTableState>
</value> </value>
</entry> </entry>
<entry key="-1834143290">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1766545009"> <entry key="-1766545009">
<value> <value>
<AndroidTestResultsTableState> <AndroidTestResultsTableState>
...@@ -113,6 +127,34 @@ ...@@ -113,6 +127,34 @@
</AndroidTestResultsTableState> </AndroidTestResultsTableState>
</value> </value>
</entry> </entry>
<entry key="-1531674397">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1528278223">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-1495363119"> <entry key="-1495363119">
<value> <value>
<AndroidTestResultsTableState> <AndroidTestResultsTableState>
...@@ -230,6 +272,20 @@ ...@@ -230,6 +272,20 @@
</AndroidTestResultsTableState> </AndroidTestResultsTableState>
</value> </value>
</entry> </entry>
<entry key="-991781541">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-693989101"> <entry key="-693989101">
<value> <value>
<AndroidTestResultsTableState> <AndroidTestResultsTableState>
...@@ -290,6 +346,20 @@ ...@@ -290,6 +346,20 @@
</AndroidTestResultsTableState> </AndroidTestResultsTableState>
</value> </value>
</entry> </entry>
<entry key="-91332955">
<value>
<AndroidTestResultsTableState>
<option name="preferredColumnWidths">
<map>
<entry key="29211JEGR13699" value="120" />
<entry key="Duration" value="90" />
<entry key="Google&#10; Pixel 6a" value="120" />
<entry key="Tests" value="360" />
</map>
</option>
</AndroidTestResultsTableState>
</value>
</entry>
<entry key="-43042216"> <entry key="-43042216">
<value> <value>
<AndroidTestResultsTableState> <AndroidTestResultsTableState>
......
package com.futo.polycentric.core package com.futo.polycentric.core
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import kotlinx.coroutines.runBlocking
import org.junit.After import org.junit.After
import org.junit.Assert import org.junit.Assert
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import userpackage.Protocol
class DatabaseTests { class DatabaseTests {
private lateinit var _db: SqlLiteDbHelper private lateinit var _db: SqlLiteDbHelper
...@@ -41,6 +43,83 @@ class DatabaseTests { ...@@ -41,6 +43,83 @@ class DatabaseTests {
Assert.assertArrayEquals(handle.processSecret.system.secretKey, secrets[0].system.secretKey) Assert.assertArrayEquals(handle.processSecret.system.secretKey, secrets[0].system.secretKey)
} }
@Test
fun deletePost() {
_db.recreate()
Store.initializeSqlLiteStore(_db)
//Create handle and post
val processHandle = ProcessHandle.create()
processHandle.addServer(TestConstants.SERVER)
val ev = processHandle.post("TEST")
runBlocking {
processHandle.fullyBackfillServers()
}
//Query local for event existing
val sev = Store.instance.getSignedEvent(ev)!!
Assert.assertEquals(ContentType.POST.value, sev.event.contentType)
var count = 0
Store.instance.enumerateSignedEvents(ev.system, ContentType.POST) {
count++
}
Assert.assertEquals(1, count)
//Query remote for event existing
runBlocking {
val events = ApiMethods.getEvents(TestConstants.SERVER, processHandle.system.toProto(), Protocol.RangesForSystem.newBuilder()
.addRangesForProcesses(
Protocol.RangesForProcess.newBuilder()
.setProcess(processHandle.processSecret.process.toProto())
.addRanges(
Protocol.Range.newBuilder()
.setLow(ev.logicalClock)
.setHigh(ev.logicalClock)
.build())
.build())
.build())
Assert.assertEquals(1, events.eventsList.size)
val sevRemote = SignedEvent.fromProto(events.eventsList.first())
Assert.assertEquals(ContentType.POST.value, sevRemote.event.contentType)
}
//Delete the event
processHandle.delete(ev.process, ev.logicalClock)
runBlocking {
processHandle.fullyBackfillServers()
}
//Query local for non existence
Assert.assertNull(null, Store.instance.getSignedEvent(ev))
count = 0
Store.instance.enumerateSignedEvents(ev.system, ContentType.POST) {
count++
}
Assert.assertEquals(0, count)
//Query remotely for non existence
runBlocking {
val events = ApiMethods.getEvents(TestConstants.SERVER, processHandle.system.toProto(), Protocol.RangesForSystem.newBuilder()
.addRangesForProcesses(
Protocol.RangesForProcess.newBuilder()
.setProcess(processHandle.processSecret.process.toProto())
.addRanges(
Protocol.Range.newBuilder()
.setLow(ev.logicalClock)
.setHigh(ev.logicalClock)
.build())
.build())
.build())
Assert.assertEquals(0, events.eventsList.size)
}
}
@After @After
fun cleanup() { fun cleanup() {
_db.close() _db.close()
......
...@@ -9,6 +9,7 @@ import androidx.test.core.app.ApplicationProvider ...@@ -9,6 +9,7 @@ import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Assert.* import org.junit.Assert.*
import org.junit.Test import org.junit.Test
...@@ -235,6 +236,77 @@ class ProcessHandleTests { ...@@ -235,6 +236,77 @@ class ProcessHandleTests {
assertEquals("alice", serverState2.username) assertEquals("alice", serverState2.username)
} }
@Test
fun deletePost() {
Store.initializeMemoryStore()
//Create handle and post
val processHandle = ProcessHandle.create()
processHandle.addServer(TestConstants.SERVER)
val ev = processHandle.post("TEST")
runBlocking {
processHandle.fullyBackfillServers()
}
//Query local for event existing
val sev = Store.instance.getSignedEvent(ev)!!
assertEquals(ContentType.POST.value, sev.event.contentType)
var count = 0
Store.instance.enumerateSignedEvents(ev.system, ContentType.POST) {
count++
}
assertEquals(1, count)
//Query remote for event existing
runBlocking {
val events = ApiMethods.getEvents(TestConstants.SERVER, processHandle.system.toProto(), Protocol.RangesForSystem.newBuilder()
.addRangesForProcesses(Protocol.RangesForProcess.newBuilder()
.setProcess(processHandle.processSecret.process.toProto())
.addRanges(Protocol.Range.newBuilder()
.setLow(ev.logicalClock)
.setHigh(ev.logicalClock)
.build())
.build())
.build())
assertEquals(1, events.eventsList.size)
val sevRemote = SignedEvent.fromProto(events.eventsList.first())
assertEquals(ContentType.POST.value, sevRemote.event.contentType)
}
//Delete the event
processHandle.delete(ev.process, ev.logicalClock)
runBlocking {
processHandle.fullyBackfillServers()
}
//Query local for non existence
count = 0
Store.instance.enumerateSignedEvents(ev.system, ContentType.POST) {
count++
}
assertEquals(0, count)
assertNull(null, Store.instance.getSignedEvent(ev))
//Query remotely for non existence
runBlocking {
val events = ApiMethods.getEvents(TestConstants.SERVER, processHandle.system.toProto(), Protocol.RangesForSystem.newBuilder()
.addRangesForProcesses(Protocol.RangesForProcess.newBuilder()
.setProcess(processHandle.processSecret.process.toProto())
.addRanges(Protocol.Range.newBuilder()
.setLow(ev.logicalClock)
.setHigh(ev.logicalClock)
.build())
.build())
.build())
assertEquals(0, events.eventsList.size)
}
}
@Test @Test
fun comment() = runTest { fun comment() = runTest {
Store.initializeMemoryStore() Store.initializeMemoryStore()
......
...@@ -56,12 +56,20 @@ class MemoryStore : Store() { ...@@ -56,12 +56,20 @@ class MemoryStore : Store() {
override fun updateProcessState(system: PublicKey, process: ByteArray, storageTypeProcessState: StorageTypeProcessState) { } override fun updateProcessState(system: PublicKey, process: ByteArray, storageTypeProcessState: StorageTypeProcessState) { }
override fun getSignedEvent(system: PublicKey, process: Process, logicalClock: Long): SignedEvent? { override fun getSignedEvent(system: PublicKey, process: Process, logicalClock: Long): SignedEvent? {
val e = _signedEvents[EventKey(system, process.process, logicalClock)]?.event ?: return null val e = _signedEvents[EventKey(system, process.process, logicalClock)] ?: return null
return SignedEvent.fromProto(e) if (!e.hasEvent()) {
return null
}
return SignedEvent.fromProto(e.event)
} }
override fun enumerateSignedEvents(system: PublicKey, contentType: ContentType?, handler: (SignedEvent) -> Unit) { override fun enumerateSignedEvents(system: PublicKey, contentType: ContentType?, handler: (SignedEvent) -> Unit) {
for (pair in _signedEvents) { for (pair in _signedEvents) {
if (!pair.value.hasEvent()) {
continue
}
if (pair.key.system != system) { if (pair.key.system != system) {
continue continue
} }
......
...@@ -252,24 +252,6 @@ class ProcessHandle constructor( ...@@ -252,24 +252,6 @@ class ProcessHandle constructor(
Ranges.insert(deleteProcessState.ranges, deleteProto.logicalClock) Ranges.insert(deleteProcessState.ranges, deleteProto.logicalClock)
Store.instance.putTombstone(event.system, deleteProcess.process, deleteProto.logicalClock, signedEvent.toPointer()) Store.instance.putTombstone(event.system, deleteProcess.process, deleteProto.logicalClock, signedEvent.toPointer())
/* TODO
actions.push(
this._store.deleteIndexClaim(
event.system,
event.process,
event.logicalClock,
),
)*/
} else if (event.contentType == ContentType.CLAIM.value) {
/* TODO
actions.push(
this._store.putIndexClaim(
event.system,
event.process,
event.logicalClock,
),
)*/
} }
systemState.update(event) systemState.update(event)
......
...@@ -59,13 +59,38 @@ class SqlLiteDbHelper : SQLiteOpenHelper { ...@@ -59,13 +59,38 @@ class SqlLiteDbHelper : SQLiteOpenHelper {
currentVersion = 3 currentVersion = 3
} }
if (currentVersion == 3 && newVersion == 4) {
db.execSQL("""
CREATE TABLE new_signed_events (
id INTEGER PRIMARY KEY,
public_key VARCHAR,
process VARCHAR,
logical_clock INTEGER,
content_type INTEGER,
value BLOB,
UNIQUE(public_key, process, logical_clock)
)
""")
db.execSQL("""
INSERT INTO new_signed_events (id, public_key, process, logical_clock, content_type, value)
SELECT MAX(id) as id, public_key, process, logical_clock, content_type, value
FROM signed_events
GROUP BY public_key, process, logical_clock
""")
db.execSQL("DROP TABLE signed_events")
db.execSQL("ALTER TABLE new_signed_events RENAME TO signed_events")
db.execSQL("CREATE INDEX idx_event_pointer ON signed_events (public_key, process, logical_clock)")
}
} }
private fun createTables(db: SQLiteDatabase) { private fun createTables(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE system_states (public_key VARCHAR PRIMARY KEY, value BLOB)") db.execSQL("CREATE TABLE system_states (public_key VARCHAR PRIMARY KEY, value BLOB)")
db.execSQL("CREATE TABLE process_states (public_key_process VARCHAR PRIMARY KEY, value BLOB)") db.execSQL("CREATE TABLE process_states (public_key_process VARCHAR PRIMARY KEY, value BLOB)")
db.execSQL("CREATE TABLE process_secrets (public_key VARCHAR PRIMARY KEY, value BLOB)") db.execSQL("CREATE TABLE process_secrets (public_key VARCHAR PRIMARY KEY, value BLOB)")
db.execSQL("CREATE TABLE signed_events (id INTEGER PRIMARY KEY, public_key VARCHAR, process VARCHAR, logical_clock INTEGER, content_type INTEGER, value BLOB)") db.execSQL("CREATE TABLE signed_events (id INTEGER PRIMARY KEY, public_key VARCHAR, process VARCHAR, logical_clock INTEGER, content_type INTEGER, value BLOB, UNIQUE(public_key, process, logical_clock))")
db.execSQL("CREATE INDEX idx_event_pointer ON signed_events (public_key, process, logical_clock)") db.execSQL("CREATE INDEX idx_event_pointer ON signed_events (public_key, process, logical_clock)")
} }
...@@ -88,6 +113,6 @@ class SqlLiteDbHelper : SQLiteOpenHelper { ...@@ -88,6 +113,6 @@ class SqlLiteDbHelper : SQLiteOpenHelper {
companion object { companion object {
private const val TAG = "SqlLiteDbHelper" private const val TAG = "SqlLiteDbHelper"
private const val DATABASE_NAME = "polycentric_core.db" private const val DATABASE_NAME = "polycentric_core.db"
private const val DATABASE_VERSION = 3 private const val DATABASE_VERSION = 4
} }
} }
\ No newline at end of file
...@@ -58,7 +58,7 @@ class SqlLiteStore(private val _db: SqlLiteDbHelper) : Store() { ...@@ -58,7 +58,7 @@ class SqlLiteStore(private val _db: SqlLiteDbHelper) : Store() {
.build() .build()
_db.writableDatabase.execSQL("REPLACE INTO signed_events(public_key, process, logical_clock, content_type, value) VALUES(?, ?, ?, 0, ?)", _db.writableDatabase.execSQL("REPLACE INTO signed_events(public_key, process, logical_clock, content_type, value) VALUES(?, ?, ?, 0, ?)",
arrayOf(system.key.toBase64(), process.toBase64(), logicalClock.toString(), storageTypeEvent.toByteArray())) arrayOf(system.key.toBase64(), process.toBase64(), logicalClock.toString(), storageTypeEvent.toByteArray()))
} }
override fun getSignedEvent(system: PublicKey, process: Process, logicalClock: Long): SignedEvent? { override fun getSignedEvent(system: PublicKey, process: Process, logicalClock: Long): SignedEvent? {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment