github.com/mre-fog/trillianxx@v1.1.2-0.20180615153820-ae375a99d36a/client/log_client_test.go (about) 1 // Copyright 2017 Google Inc. 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 client 16 17 import ( 18 "bytes" 19 "context" 20 "fmt" 21 "testing" 22 "time" 23 24 "github.com/google/trillian" 25 "github.com/google/trillian/testonly/integration" 26 "google.golang.org/grpc/codes" 27 "google.golang.org/grpc/status" 28 29 "github.com/google/trillian/storage/testdb" 30 stestonly "github.com/google/trillian/storage/testonly" 31 ) 32 33 func TestAddGetLeaf(t *testing.T) { 34 // TODO: Build a GetLeaf method and test a full get/set cycle. 35 } 36 37 // addSequencedLeaves is a temporary stand-in function for tests until the real API gets built. 38 func addSequencedLeaves(ctx context.Context, env *integration.LogEnv, client *LogClient, leaves [][]byte) error { 39 if len(leaves) == 0 { 40 return nil 41 } 42 for i, l := range leaves { 43 if err := client.AddSequencedLeaf(ctx, l, int64(i)); err != nil { 44 return fmt.Errorf("AddSequencedLeaf(): %v", err) 45 } 46 } 47 env.Sequencer.OperationSingle(ctx) 48 if err := client.WaitForInclusion(ctx, leaves[len(leaves)-1]); err != nil { 49 return fmt.Errorf("WaitForInclusion(): %v", err) 50 } 51 return nil 52 } 53 54 func TestGetByIndex(t *testing.T) { 55 testdb.SkipIfNoMySQL(t) 56 ctx := context.Background() 57 env, err := integration.NewLogEnv(ctx, 1, "unused") 58 if err != nil { 59 t.Fatal(err) 60 } 61 defer env.Close() 62 63 tree, err := CreateAndInitTree(ctx, 64 &trillian.CreateTreeRequest{Tree: stestonly.PreorderedLogTree}, 65 env.Admin, nil, env.Log) 66 if err != nil { 67 t.Fatalf("Failed to create log: %v", err) 68 } 69 70 client, err := NewFromTree(env.Log, tree) 71 if err != nil { 72 t.Fatalf("NewFromTree(): %v", err) 73 } 74 // Add a few test leaves. 75 leafData := [][]byte{ 76 []byte("A"), 77 []byte("B"), 78 []byte("C"), 79 } 80 81 if err := addSequencedLeaves(ctx, env, client, leafData); err != nil { 82 t.Fatalf("Failed to add leaves: %v", err) 83 } 84 85 for i, l := range leafData { 86 leaf, err := client.GetByIndex(ctx, int64(i)) 87 if err != nil { 88 t.Errorf("Failed to GetByIndex(%v): %v", i, err) 89 continue 90 } 91 if got, want := leaf.LeafValue, l; !bytes.Equal(got, want) { 92 t.Errorf("GetByIndex(%v) = %x, want %x", i, got, want) 93 } 94 } 95 } 96 97 func TestListByIndex(t *testing.T) { 98 testdb.SkipIfNoMySQL(t) 99 ctx := context.Background() 100 env, err := integration.NewLogEnv(ctx, 1, "unused") 101 if err != nil { 102 t.Fatal(err) 103 } 104 defer env.Close() 105 tree, err := CreateAndInitTree(ctx, 106 &trillian.CreateTreeRequest{Tree: stestonly.PreorderedLogTree}, 107 env.Admin, nil, env.Log) 108 if err != nil { 109 t.Fatalf("Failed to create log: %v", err) 110 } 111 112 client, err := NewFromTree(env.Log, tree) 113 if err != nil { 114 t.Fatalf("NewFromTree(): %v", err) 115 } 116 // Add a few test leaves. 117 leafData := [][]byte{ 118 []byte("A"), 119 []byte("B"), 120 []byte("C"), 121 } 122 123 if err := addSequencedLeaves(ctx, env, client, leafData); err != nil { 124 t.Fatalf("Failed to add leaves: %v", err) 125 } 126 127 // Fetch leaves. 128 leaves, err := client.ListByIndex(ctx, 0, 3) 129 if err != nil { 130 t.Errorf("Failed to ListByIndex: %v", err) 131 } 132 for i, l := range leaves { 133 if got, want := l.LeafValue, leafData[i]; !bytes.Equal(got, want) { 134 t.Errorf("ListIndex()[%v] = %v, want %v", i, got, want) 135 } 136 } 137 } 138 139 func TestVerifyInclusion(t *testing.T) { 140 testdb.SkipIfNoMySQL(t) 141 ctx := context.Background() 142 env, err := integration.NewLogEnv(ctx, 1, "unused") 143 if err != nil { 144 t.Fatal(err) 145 } 146 defer env.Close() 147 tree, err := CreateAndInitTree(ctx, 148 &trillian.CreateTreeRequest{Tree: stestonly.PreorderedLogTree}, 149 env.Admin, nil, env.Log) 150 if err != nil { 151 t.Fatalf("Failed to create log: %v", err) 152 } 153 154 client, err := NewFromTree(env.Log, tree) 155 if err != nil { 156 t.Fatalf("NewFromTree(): %v", err) 157 } 158 // Add a few test leaves. 159 leafData := [][]byte{ 160 []byte("A"), 161 []byte("B"), 162 } 163 164 if err := addSequencedLeaves(ctx, env, client, leafData); err != nil { 165 t.Fatalf("Failed to add leaves: %v", err) 166 } 167 168 for _, l := range leafData { 169 if err := client.VerifyInclusion(ctx, l); err != nil { 170 t.Errorf("VerifyInclusion(%s) = %v, want nil", l, err) 171 } 172 } 173 } 174 175 func TestVerifyInclusionAtIndex(t *testing.T) { 176 testdb.SkipIfNoMySQL(t) 177 ctx := context.Background() 178 env, err := integration.NewLogEnv(ctx, 1, "unused") 179 if err != nil { 180 t.Fatal(err) 181 } 182 defer env.Close() 183 tree, err := CreateAndInitTree(ctx, 184 &trillian.CreateTreeRequest{Tree: stestonly.PreorderedLogTree}, 185 env.Admin, nil, env.Log) 186 if err != nil { 187 t.Fatalf("Failed to create log: %v", err) 188 } 189 190 client, err := NewFromTree(env.Log, tree) 191 if err != nil { 192 t.Fatalf("NewFromTree(): %v", err) 193 } 194 // Add a few test leaves. 195 leafData := [][]byte{ 196 []byte("A"), 197 []byte("B"), 198 } 199 200 if err := addSequencedLeaves(ctx, env, client, leafData); err != nil { 201 t.Fatalf("Failed to add leaves: %v", err) 202 } 203 204 for i, l := range leafData { 205 if err := client.GetAndVerifyInclusionAtIndex(ctx, l, int64(i)); err != nil { 206 t.Errorf("VerifyInclusion(%s) = %v, want nil", l, err) 207 } 208 } 209 } 210 211 func TestWaitForInclusion(t *testing.T) { 212 testdb.SkipIfNoMySQL(t) 213 ctx := context.Background() 214 env, err := integration.NewLogEnv(ctx, 0, "unused") 215 if err != nil { 216 t.Fatal(err) 217 } 218 defer env.Close() 219 tree, err := CreateAndInitTree(ctx, 220 &trillian.CreateTreeRequest{Tree: stestonly.LogTree}, 221 env.Admin, nil, env.Log) 222 if err != nil { 223 t.Fatalf("Failed to create log: %v", err) 224 } 225 226 for _, test := range []struct { 227 desc string 228 leaf []byte 229 client trillian.TrillianLogClient 230 skipPreCheck bool 231 wantErr bool 232 }{ 233 {desc: "First leaf", leaf: []byte("A"), client: env.Log}, 234 {desc: "Make TreeSize > 1", leaf: []byte("B"), client: env.Log}, 235 {desc: "invalid inclusion proof", leaf: []byte("A"), skipPreCheck: true, 236 client: &MockLogClient{c: env.Log, mGetInclusionProof: true}, wantErr: true}, 237 } { 238 t.Run(test.desc, func(t *testing.T) { 239 client, err := NewFromTree(test.client, tree) 240 if err != nil { 241 t.Fatalf("NewFromTree(): %v", err) 242 } 243 244 if !test.skipPreCheck { 245 cctx, cancel := context.WithTimeout(ctx, 50*time.Millisecond) 246 if err := client.WaitForInclusion(cctx, test.leaf); status.Code(err) != codes.DeadlineExceeded { 247 t.Errorf("WaitForInclusion before sequencing: %v, want: not-nil", err) 248 } 249 cancel() 250 } 251 252 if err := client.QueueLeaf(ctx, test.leaf); err != nil { 253 t.Fatalf("QueueLeaf(): %v", err) 254 } 255 env.Sequencer.OperationSingle(ctx) 256 err = client.WaitForInclusion(ctx, test.leaf) 257 if got := err != nil; got != test.wantErr { 258 t.Errorf("WaitForInclusion(): %v, want error: %v", err, test.wantErr) 259 } 260 }) 261 } 262 } 263 264 func TestUpdateRoot(t *testing.T) { 265 testdb.SkipIfNoMySQL(t) 266 ctx := context.Background() 267 env, err := integration.NewLogEnv(ctx, 1, "unused") 268 if err != nil { 269 t.Fatal(err) 270 } 271 defer env.Close() 272 tree, err := CreateAndInitTree(ctx, 273 &trillian.CreateTreeRequest{Tree: stestonly.LogTree}, 274 env.Admin, nil, env.Log) 275 if err != nil { 276 t.Fatalf("Failed to create log: %v", err) 277 } 278 279 client, err := NewFromTree(env.Log, tree) 280 if err != nil { 281 t.Fatalf("NewFromTree(): %v", err) 282 } 283 284 before := client.root.TreeSize 285 286 // UpdateRoot should succeed with no change. 287 root, err := client.UpdateRoot(ctx) 288 if err != nil { 289 t.Fatalf("UpdateRoot(): %v", err) 290 } 291 if got, want := root.TreeSize, before; got != want { 292 t.Errorf("Tree size changed unexpectedly: %v, want %v", got, want) 293 } 294 295 data := []byte("foo") 296 if err := client.QueueLeaf(ctx, data); err != nil { 297 t.Fatalf("QueueLeaf(%s): %v, want nil", data, err) 298 } 299 300 env.Sequencer.OperationSingle(ctx) 301 302 // UpdateRoot should see a change. 303 root, err = client.UpdateRoot(ctx) 304 if err != nil { 305 t.Fatalf("UpdateRoot(): %v", err) 306 } 307 if got, want := root.TreeSize, before; got <= want { 308 t.Errorf("Tree size after add Leaf: %v, want > %v", got, want) 309 } 310 }