github.com/transparency-dev/armored-witness-applet@v0.1.1/trusted_applet/internal/storage/slots/slots_test.go (about) 1 // Copyright 2022 The Armored Witness Applet authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package slots 16 17 import ( 18 "fmt" 19 "testing" 20 21 "github.com/google/go-cmp/cmp" 22 "github.com/transparency-dev/armored-witness-applet/trusted_applet/internal/storage/testonly" 23 ) 24 25 func TestOpenPartition(t *testing.T) { 26 type slotGeo struct { 27 Start uint 28 Length uint 29 } 30 toSlotGeo := func(in []Slot) []slotGeo { 31 r := make([]slotGeo, len(in)) 32 for i := range in { 33 r[i] = slotGeo{ 34 Start: in[i].start, 35 Length: in[i].length, 36 } 37 } 38 return r 39 } 40 41 const devBlockSize = 32 42 43 for _, test := range []struct { 44 name string 45 geo Geometry 46 wantErr bool 47 wantSlots []slotGeo 48 }{ 49 { 50 name: "free space remaining", 51 geo: Geometry{ 52 Start: 10, 53 Length: 10, 54 SlotLengths: []uint{1, 1, 2, 4}, 55 }, 56 wantSlots: []slotGeo{ 57 {Start: 10, Length: 1}, 58 {Start: 11, Length: 1}, 59 {Start: 12, Length: 2}, 60 {Start: 14, Length: 4}, 61 }, 62 }, { 63 name: "fully allocated", 64 geo: Geometry{ 65 Start: 10, 66 Length: 10, 67 SlotLengths: []uint{1, 1, 2, 4, 2}, 68 }, 69 wantSlots: []slotGeo{ 70 {Start: 10, Length: 1}, 71 {Start: 11, Length: 1}, 72 {Start: 12, Length: 2}, 73 {Start: 14, Length: 4}, 74 {Start: 18, Length: 2}, 75 }, 76 }, { 77 name: "over allocated", 78 geo: Geometry{ 79 Start: 10, 80 Length: 10, 81 SlotLengths: []uint{1, 1, 2, 4, 3}, 82 }, 83 wantErr: true, 84 }, 85 } { 86 t.Run(test.name, func(t *testing.T) { 87 dev := testonly.NewMemDev(t, devBlockSize) 88 p, err := OpenPartition(dev, test.geo) 89 if gotErr := err != nil; gotErr != test.wantErr { 90 t.Fatalf("Got %v, wantErr %t", err, test.wantErr) 91 } 92 if test.wantErr { 93 return 94 } 95 if diff := cmp.Diff(toSlotGeo(p.slots), test.wantSlots); diff != "" { 96 t.Fatalf("Got diff: %s", diff) 97 } 98 }) 99 } 100 } 101 102 func memPartition(t *testing.T) (*Partition, *testonly.MemDev) { 103 t.Helper() 104 md := testonly.NewMemDev(t, 32) 105 geo := Geometry{ 106 Start: 10, 107 Length: 10, 108 SlotLengths: []uint{1, 1, 2, 4}, 109 } 110 p, err := OpenPartition(md, geo) 111 if err != nil { 112 t.Fatalf("Failed to create mem partition: %v", err) 113 } 114 return p, md 115 } 116 117 func TestOpenSlot(t *testing.T) { 118 p, _ := memPartition(t) 119 for _, test := range []struct { 120 name string 121 slot uint 122 wantErr bool 123 }{ 124 { 125 name: "works", 126 slot: 0, 127 }, { 128 name: "invalid slot: too big", 129 slot: uint(len(p.slots)), 130 wantErr: true, 131 }, 132 } { 133 t.Run(test.name, func(t *testing.T) { 134 _, err := p.Open(test.slot) 135 if gotErr := err != nil; gotErr != test.wantErr { 136 t.Fatalf("Failed to open slot: %v", err) 137 } 138 }) 139 } 140 } 141 142 func TestErase(t *testing.T) { 143 p, _ := memPartition(t) 144 145 // Create some data in each slot 146 for i := 0; i < p.NumSlots(); i++ { 147 s, err := p.Open(uint(i)) 148 if err != nil { 149 t.Fatalf("Failed to open slot %d: %v", i, err) 150 } 151 s.Write([]byte(fmt.Sprintf("data for slot %d", i))) 152 } 153 154 // Verify slots contain _something_ 155 for i := 0; i < p.NumSlots(); i++ { 156 d, r := openAndRead(t, p, uint(i)) 157 if got, want := r, uint32(1); got != want { 158 t.Fatalf("Got data with revision %d, want %d", got, want) 159 } 160 if len(d) == 0 { 161 t.Fatal("Got unexpected zero length data") 162 } 163 } 164 165 // Erase all the slots 166 if err := p.Erase(); err != nil { 167 t.Fatalf("Failed to erase partition: %v", err) 168 } 169 170 // All slots should now be empty 171 for i := 0; i < p.NumSlots(); i++ { 172 d, r := openAndRead(t, p, uint(i)) 173 if got, want := r, uint32(0); got != want { 174 t.Fatalf("Got data with revision %d, want %d", got, want) 175 } 176 if len(d) != 0 { 177 t.Fatalf("Got unexpected data: %x", d) 178 } 179 } 180 } 181 182 func openAndRead(t *testing.T, p *Partition, i uint) ([]byte, uint32) { 183 t.Helper() 184 s, err := p.Open(uint(i)) 185 if err != nil { 186 t.Fatalf("Failed to open slot %d: %v", i, err) 187 } 188 d, r, err := s.Read() 189 if err != nil { 190 t.Fatalf("Failed to read slot %d: %v", i, err) 191 } 192 return d, r 193 }