1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
package storage
import (
"testing"
"time"
"github.com/Fuwn/plutia/internal/types"
)
func TestApplyOperationsBatch_DurabilityBetweenBatches(t *testing.T) {
tmp := t.TempDir()
store, err := OpenPebble(tmp)
if err != nil {
t.Fatalf("open pebble: %v", err)
}
makeMutation := func(did string, seq uint64) OperationMutation {
return OperationMutation{
State: types.StateV1{
Version: 1,
DID: did,
DIDDocument: []byte(`{"id":"` + did + `"}`),
ChainTipHash: "sha256:tip",
LatestOpSeq: seq,
UpdatedAt: time.Now().UTC(),
},
Ref: &types.BlockRefV1{
Version: 1,
BlockID: 1,
OpSeq: seq,
DID: did,
CID: "sha256:cid",
},
}
}
if err := store.ApplyOperationsBatch([]OperationMutation{
makeMutation("did:plc:a", 1),
makeMutation("did:plc:b", 2),
}, []BlockHashEntry{{BlockID: 1, Hash: "abc"}}); err != nil {
t.Fatalf("apply first batch: %v", err)
}
if err := store.Close(); err != nil {
t.Fatalf("close store: %v", err)
}
// Simulate a crash before the second batch commit by reopening without applying it.
reopened, err := OpenPebble(tmp)
if err != nil {
t.Fatalf("reopen pebble: %v", err)
}
defer reopened.Close()
seq, err := reopened.GetGlobalSeq()
if err != nil {
t.Fatalf("get global seq: %v", err)
}
if seq != 2 {
t.Fatalf("global seq mismatch after simulated crash: got %d want 2", seq)
}
if _, ok, err := reopened.GetOpSeqRef(3); err != nil {
t.Fatalf("get opseq 3: %v", err)
} else if ok {
t.Fatalf("unexpected opseq ref for uncommitted sequence 3")
}
}
|