github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/asserts/pool_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package asserts_test 21 22 import ( 23 "errors" 24 "sort" 25 26 . "gopkg.in/check.v1" 27 28 "github.com/snapcore/snapd/asserts" 29 "github.com/snapcore/snapd/asserts/assertstest" 30 "github.com/snapcore/snapd/testutil" 31 ) 32 33 type poolSuite struct { 34 testutil.BaseTest 35 36 hub *assertstest.StoreStack 37 dev1Acct *asserts.Account 38 dev2Acct *asserts.Account 39 40 decl1 *asserts.TestOnlyDecl 41 decl1_1 *asserts.TestOnlyDecl 42 rev1_1111 *asserts.TestOnlyRev 43 rev1_3333 *asserts.TestOnlyRev 44 45 decl2 *asserts.TestOnlyDecl 46 rev2_2222 *asserts.TestOnlyRev 47 48 db *asserts.Database 49 } 50 51 var _ = Suite(&poolSuite{}) 52 53 func (s *poolSuite) SetUpTest(c *C) { 54 s.BaseTest.SetUpTest(c) 55 56 s.hub = assertstest.NewStoreStack("hub", nil) 57 s.dev1Acct = assertstest.NewAccount(s.hub, "developer1", map[string]interface{}{ 58 "account-id": "developer1", 59 }, "") 60 s.dev2Acct = assertstest.NewAccount(s.hub, "developer2", map[string]interface{}{ 61 "account-id": "developer2", 62 }, "") 63 64 a, err := s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{ 65 "id": "one", 66 "dev-id": "developer1", 67 }, nil, "") 68 c.Assert(err, IsNil) 69 s.decl1 = a.(*asserts.TestOnlyDecl) 70 71 a, err = s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{ 72 "id": "one", 73 "dev-id": "developer1", 74 "revision": "1", 75 }, nil, "") 76 c.Assert(err, IsNil) 77 s.decl1_1 = a.(*asserts.TestOnlyDecl) 78 79 a, err = s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{ 80 "id": "two", 81 "dev-id": "developer2", 82 }, nil, "") 83 c.Assert(err, IsNil) 84 s.decl2 = a.(*asserts.TestOnlyDecl) 85 86 a, err = s.hub.Sign(asserts.TestOnlyRevType, map[string]interface{}{ 87 "h": "1111", 88 "id": "one", 89 "dev-id": "developer1", 90 }, nil, "") 91 c.Assert(err, IsNil) 92 s.rev1_1111 = a.(*asserts.TestOnlyRev) 93 94 a, err = s.hub.Sign(asserts.TestOnlyRevType, map[string]interface{}{ 95 "h": "3333", 96 "id": "one", 97 "dev-id": "developer1", 98 }, nil, "") 99 c.Assert(err, IsNil) 100 s.rev1_3333 = a.(*asserts.TestOnlyRev) 101 102 a, err = s.hub.Sign(asserts.TestOnlyRevType, map[string]interface{}{ 103 "h": "2222", 104 "id": "two", 105 "dev-id": "developer2", 106 }, nil, "") 107 c.Assert(err, IsNil) 108 s.rev2_2222 = a.(*asserts.TestOnlyRev) 109 110 db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{ 111 Backstore: asserts.NewMemoryBackstore(), 112 Trusted: s.hub.Trusted, 113 }) 114 c.Assert(err, IsNil) 115 s.db = db 116 } 117 118 func (s *poolSuite) TestAddUnresolved(c *C) { 119 pool := asserts.NewPool(s.db, 64) 120 121 at1 := &asserts.AtRevision{ 122 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 123 Revision: asserts.RevisionNotKnown, 124 } 125 err := pool.AddUnresolved(at1, "for_one") // group num: 0 126 c.Assert(err, IsNil) 127 128 toResolve, err := pool.ToResolve() 129 c.Assert(err, IsNil) 130 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 131 asserts.MakePoolGrouping(0): {at1}, 132 }) 133 } 134 135 func (s *poolSuite) TestAddUnresolvedPredefined(c *C) { 136 pool := asserts.NewPool(s.db, 64) 137 138 at := s.hub.TrustedAccount.At() 139 at.Revision = asserts.RevisionNotKnown 140 err := pool.AddUnresolved(at, "for_one") 141 c.Assert(err, IsNil) 142 143 // nothing to resolve 144 toResolve, err := pool.ToResolve() 145 c.Assert(err, IsNil) 146 c.Check(toResolve, HasLen, 0) 147 } 148 149 func (s *poolSuite) TestAddUnresolvedGrouping(c *C) { 150 pool := asserts.NewPool(s.db, 64) 151 152 storeKeyAt := s.hub.StoreAccountKey("").At() 153 154 pool.AddUnresolved(storeKeyAt, "for_two") // group num: 0 155 pool.AddUnresolved(storeKeyAt, "for_one") // group num: 1 156 157 toResolve, err := pool.ToResolve() 158 c.Assert(err, IsNil) 159 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 160 asserts.MakePoolGrouping(0, 1): {storeKeyAt}, 161 }) 162 } 163 164 func (s *poolSuite) TestAddUnresolvedDup(c *C) { 165 pool := asserts.NewPool(s.db, 64) 166 167 storeKeyAt := s.hub.StoreAccountKey("").At() 168 169 pool.AddUnresolved(storeKeyAt, "for_one") // group num: 0 170 pool.AddUnresolved(storeKeyAt, "for_one") // group num: 0 171 172 toResolve, err := pool.ToResolve() 173 c.Assert(err, IsNil) 174 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 175 asserts.MakePoolGrouping(0): {storeKeyAt}, 176 }) 177 } 178 179 type byAtRevision []*asserts.AtRevision 180 181 func (ats byAtRevision) Len() int { 182 return len(ats) 183 } 184 185 func (ats byAtRevision) Less(i, j int) bool { 186 return ats[i].Ref.Unique() < ats[j].Ref.Unique() 187 } 188 189 func (ats byAtRevision) Swap(i, j int) { 190 ats[i], ats[j] = ats[j], ats[i] 191 } 192 193 func sortToResolve(toResolve map[asserts.Grouping][]*asserts.AtRevision) { 194 for _, ats := range toResolve { 195 sort.Sort(byAtRevision(ats)) 196 } 197 } 198 199 func (s *poolSuite) TestFetch(c *C) { 200 pool := asserts.NewPool(s.db, 64) 201 202 at1111 := &asserts.AtRevision{ 203 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 204 Revision: asserts.RevisionNotKnown, 205 } 206 err := pool.AddUnresolved(at1111, "for_one") 207 c.Assert(err, IsNil) 208 209 toResolve, err := pool.ToResolve() 210 c.Assert(err, IsNil) 211 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 212 asserts.MakePoolGrouping(0): {at1111}, 213 }) 214 215 ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 216 c.Assert(err, IsNil) 217 c.Assert(ok, Equals, true) 218 219 toResolve, err = pool.ToResolve() 220 c.Assert(err, IsNil) 221 sortToResolve(toResolve) 222 dev1AcctAt := s.dev1Acct.At() 223 dev1AcctAt.Revision = asserts.RevisionNotKnown 224 decl1At := s.decl1.At() 225 decl1At.Revision = asserts.RevisionNotKnown 226 storeKeyAt := s.hub.StoreAccountKey("").At() 227 storeKeyAt.Revision = asserts.RevisionNotKnown 228 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 229 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt, decl1At}, 230 }) 231 232 c.Check(pool.Err("for_one"), IsNil) 233 } 234 235 func (s *poolSuite) TestCompleteFetch(c *C) { 236 pool := asserts.NewPool(s.db, 64) 237 238 at1111 := &asserts.AtRevision{ 239 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 240 Revision: asserts.RevisionNotKnown, 241 } 242 err := pool.AddUnresolved(at1111, "for_one") 243 c.Assert(err, IsNil) 244 245 toResolve, err := pool.ToResolve() 246 c.Assert(err, IsNil) 247 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 248 asserts.MakePoolGrouping(0): {at1111}, 249 }) 250 251 ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 252 c.Assert(err, IsNil) 253 c.Assert(ok, Equals, true) 254 255 toResolve, err = pool.ToResolve() 256 c.Assert(err, IsNil) 257 sortToResolve(toResolve) 258 dev1AcctAt := s.dev1Acct.At() 259 dev1AcctAt.Revision = asserts.RevisionNotKnown 260 decl1At := s.decl1.At() 261 decl1At.Revision = asserts.RevisionNotKnown 262 storeKey := s.hub.StoreAccountKey("") 263 storeKeyAt := storeKey.At() 264 storeKeyAt.Revision = asserts.RevisionNotKnown 265 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 266 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt, decl1At}, 267 }) 268 269 b := asserts.NewBatch(nil) 270 err = b.Add(s.decl1) 271 c.Assert(err, IsNil) 272 err = b.Add(storeKey) 273 c.Assert(err, IsNil) 274 err = b.Add(s.dev1Acct) 275 c.Assert(err, IsNil) 276 277 ok, err = pool.AddBatch(b, asserts.MakePoolGrouping(0)) 278 c.Assert(err, IsNil) 279 c.Assert(ok, Equals, true) 280 281 toResolve, err = pool.ToResolve() 282 c.Assert(err, IsNil) 283 c.Check(toResolve, HasLen, 0) 284 285 c.Check(pool.Err("for_one"), IsNil) 286 287 err = pool.CommitTo(s.db) 288 c.Check(err, IsNil) 289 c.Assert(pool.Err("for_one"), IsNil) 290 291 a, err := at1111.Ref.Resolve(s.db.Find) 292 c.Assert(err, IsNil) 293 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111") 294 } 295 296 func (s *poolSuite) TestPushSuggestionForPrerequisite(c *C) { 297 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 298 299 pool := asserts.NewPool(s.db, 64) 300 301 at1111 := &asserts.AtRevision{ 302 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 303 Revision: asserts.RevisionNotKnown, 304 } 305 err := pool.AddUnresolved(at1111, "for_one") 306 c.Assert(err, IsNil) 307 308 toResolve, err := pool.ToResolve() 309 c.Assert(err, IsNil) 310 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 311 asserts.MakePoolGrouping(0): {at1111}, 312 }) 313 314 ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 315 c.Assert(err, IsNil) 316 c.Assert(ok, Equals, true) 317 318 // push prerequisite suggestion 319 ok, err = pool.Add(s.decl1, asserts.MakePoolGrouping(0)) 320 c.Assert(err, IsNil) 321 c.Assert(ok, Equals, true) 322 323 toResolve, err = pool.ToResolve() 324 c.Assert(err, IsNil) 325 sortToResolve(toResolve) 326 dev1AcctAt := s.dev1Acct.At() 327 dev1AcctAt.Revision = asserts.RevisionNotKnown 328 storeKey := s.hub.StoreAccountKey("") 329 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 330 asserts.MakePoolGrouping(0): {storeKey.At(), dev1AcctAt}, 331 }) 332 333 c.Check(pool.Err("for_one"), IsNil) 334 335 ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 336 c.Assert(err, IsNil) 337 c.Assert(ok, Equals, true) 338 339 toResolve, err = pool.ToResolve() 340 c.Assert(err, IsNil) 341 c.Check(toResolve, HasLen, 0) 342 343 c.Check(pool.Err("for_one"), IsNil) 344 345 err = pool.CommitTo(s.db) 346 c.Check(err, IsNil) 347 c.Assert(pool.Err("for_one"), IsNil) 348 349 a, err := at1111.Ref.Resolve(s.db.Find) 350 c.Assert(err, IsNil) 351 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111") 352 } 353 354 func (s *poolSuite) TestPushSuggestionForNew(c *C) { 355 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 356 357 pool := asserts.NewPool(s.db, 64) 358 359 atOne := &asserts.AtRevision{ 360 Ref: asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}}, 361 Revision: asserts.RevisionNotKnown, 362 } 363 err := pool.AddUnresolved(atOne, "for_one") 364 c.Assert(err, IsNil) 365 366 toResolve, err := pool.ToResolve() 367 c.Assert(err, IsNil) 368 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 369 asserts.MakePoolGrouping(0): {atOne}, 370 }) 371 372 ok, err := pool.Add(s.decl1, asserts.MakePoolGrouping(0)) 373 c.Assert(err, IsNil) 374 c.Assert(ok, Equals, true) 375 376 // new push suggestion 377 ok, err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 378 c.Assert(err, IsNil) 379 c.Assert(ok, Equals, true) 380 381 toResolve, err = pool.ToResolve() 382 c.Assert(err, IsNil) 383 sortToResolve(toResolve) 384 dev1AcctAt := s.dev1Acct.At() 385 dev1AcctAt.Revision = asserts.RevisionNotKnown 386 storeKeyAt := s.hub.StoreAccountKey("").At() 387 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 388 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt}, 389 }) 390 391 c.Check(pool.Err("for_one"), IsNil) 392 393 ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 394 c.Assert(err, IsNil) 395 c.Assert(ok, Equals, true) 396 397 toResolve, err = pool.ToResolve() 398 c.Assert(err, IsNil) 399 c.Check(toResolve, HasLen, 0) 400 401 c.Check(pool.Err("for_one"), IsNil) 402 403 err = pool.CommitTo(s.db) 404 c.Check(err, IsNil) 405 c.Assert(pool.Err("for_one"), IsNil) 406 407 a, err := s.rev1_1111.Ref().Resolve(s.db.Find) 408 c.Assert(err, IsNil) 409 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111") 410 } 411 412 func (s *poolSuite) TestPushSuggestionForNewViaBatch(c *C) { 413 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 414 415 pool := asserts.NewPool(s.db, 64) 416 417 atOne := &asserts.AtRevision{ 418 Ref: asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}}, 419 Revision: asserts.RevisionNotKnown, 420 } 421 err := pool.AddUnresolved(atOne, "for_one") 422 c.Assert(err, IsNil) 423 424 toResolve, err := pool.ToResolve() 425 c.Assert(err, IsNil) 426 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 427 asserts.MakePoolGrouping(0): {atOne}, 428 }) 429 430 b := asserts.NewBatch(nil) 431 err = b.Add(s.decl1) 432 c.Assert(err, IsNil) 433 434 // new push suggestions 435 err = b.Add(s.rev1_1111) 436 c.Assert(err, IsNil) 437 err = b.Add(s.rev1_3333) 438 c.Assert(err, IsNil) 439 440 ok, err := pool.AddBatch(b, asserts.MakePoolGrouping(0)) 441 c.Assert(err, IsNil) 442 c.Assert(ok, Equals, true) 443 444 toResolve, err = pool.ToResolve() 445 c.Assert(err, IsNil) 446 sortToResolve(toResolve) 447 dev1AcctAt := s.dev1Acct.At() 448 dev1AcctAt.Revision = asserts.RevisionNotKnown 449 storeKeyAt := s.hub.StoreAccountKey("").At() 450 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 451 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt}, 452 }) 453 454 c.Check(pool.Err("for_one"), IsNil) 455 456 ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 457 c.Assert(err, IsNil) 458 c.Assert(ok, Equals, true) 459 460 toResolve, err = pool.ToResolve() 461 c.Assert(err, IsNil) 462 c.Check(toResolve, HasLen, 0) 463 464 c.Check(pool.Err("for_one"), IsNil) 465 466 err = pool.CommitTo(s.db) 467 c.Check(err, IsNil) 468 c.Assert(pool.Err("for_one"), IsNil) 469 470 a, err := s.rev1_1111.Ref().Resolve(s.db.Find) 471 c.Assert(err, IsNil) 472 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111") 473 474 a, err = s.rev1_3333.Ref().Resolve(s.db.Find) 475 c.Assert(err, IsNil) 476 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "3333") 477 } 478 479 func (s *poolSuite) TestAddUnresolvedUnresolved(c *C) { 480 pool := asserts.NewPool(s.db, 64) 481 482 at1 := &asserts.AtRevision{ 483 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 484 Revision: asserts.RevisionNotKnown, 485 } 486 err := pool.AddUnresolved(at1, "for_one") 487 c.Assert(err, IsNil) 488 489 toResolve, err := pool.ToResolve() 490 c.Assert(err, IsNil) 491 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 492 asserts.MakePoolGrouping(0): {at1}, 493 }) 494 495 toResolve, err = pool.ToResolve() 496 c.Assert(err, IsNil) 497 c.Check(toResolve, HasLen, 0) 498 499 c.Check(pool.Err("for_one"), Equals, asserts.ErrUnresolved) 500 } 501 502 func (s *poolSuite) TestAddFormatTooNew(c *C) { 503 pool := asserts.NewPool(s.db, 64) 504 505 _, err := pool.ToResolve() 506 c.Assert(err, IsNil) 507 508 var a asserts.Assertion 509 (func() { 510 restore := asserts.MockMaxSupportedFormat(asserts.TestOnlyDeclType, 2) 511 defer restore() 512 513 a, err = s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{ 514 "id": "three", 515 "dev-id": "developer1", 516 "format": "2", 517 }, nil, "") 518 c.Assert(err, IsNil) 519 })() 520 521 gSuggestion, err := pool.Singleton("suggestion") 522 c.Assert(err, IsNil) 523 524 ok, err := pool.Add(a, gSuggestion) 525 c.Check(err, IsNil) 526 c.Check(ok, Equals, false) 527 c.Assert(pool.Err("suggestion"), ErrorMatches, `proposed "test-only-decl" assertion has format 2 but 0 is latest supported`) 528 } 529 530 func (s *poolSuite) TestAddOlderIgnored(c *C) { 531 pool := asserts.NewPool(s.db, 64) 532 533 _, err := pool.ToResolve() 534 c.Assert(err, IsNil) 535 536 gSuggestion, err := pool.Singleton("suggestion") 537 c.Assert(err, IsNil) 538 539 ok, err := pool.Add(s.decl1_1, gSuggestion) 540 c.Assert(err, IsNil) 541 c.Assert(ok, Equals, true) 542 543 ok, err = pool.Add(s.decl1, gSuggestion) 544 c.Assert(err, IsNil) 545 c.Assert(ok, Equals, true) 546 547 toResolve, err := pool.ToResolve() 548 c.Assert(err, IsNil) 549 sortToResolve(toResolve) 550 dev1AcctAt := s.dev1Acct.At() 551 dev1AcctAt.Revision = asserts.RevisionNotKnown 552 storeKeyAt := s.hub.StoreAccountKey("").At() 553 storeKeyAt.Revision = asserts.RevisionNotKnown 554 555 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 556 gSuggestion: {storeKeyAt, dev1AcctAt}, 557 }) 558 } 559 560 func (s *poolSuite) TestUnknownGroup(c *C) { 561 pool := asserts.NewPool(s.db, 64) 562 563 _, err := pool.Singleton("suggestion") 564 c.Assert(err, IsNil) 565 // sanity 566 c.Check(pool.Err("suggestion"), IsNil) 567 568 c.Check(pool.Err("foo"), Equals, asserts.ErrUnknownPoolGroup) 569 } 570 571 func (s *poolSuite) TestAddCurrentRevision(c *C) { 572 assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.dev1Acct, s.decl1) 573 574 pool := asserts.NewPool(s.db, 64) 575 576 atDev1Acct := s.dev1Acct.At() 577 atDev1Acct.Revision = asserts.RevisionNotKnown 578 err := pool.AddUnresolved(atDev1Acct, "one") 579 c.Assert(err, IsNil) 580 581 atDecl1 := s.decl1.At() 582 atDecl1.Revision = asserts.RevisionNotKnown 583 err = pool.AddUnresolved(atDecl1, "one") 584 c.Assert(err, IsNil) 585 586 toResolve, err := pool.ToResolve() 587 c.Assert(err, IsNil) 588 sortToResolve(toResolve) 589 590 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 591 asserts.MakePoolGrouping(0): {s.dev1Acct.At(), s.decl1.At()}, 592 }) 593 594 // re-adding of current revisions, is not what we expect 595 // but needs not to produce unneeded roundtrips 596 597 ok, err := pool.Add(s.hub.StoreAccountKey(""), asserts.MakePoolGrouping(0)) 598 c.Assert(err, IsNil) 599 c.Assert(ok, Equals, true) 600 601 // this will be kept marked as unresolved until the ToResolve 602 ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 603 c.Assert(err, IsNil) 604 c.Assert(ok, Equals, true) 605 606 ok, err = pool.Add(s.decl1_1, asserts.MakePoolGrouping(0)) 607 c.Assert(err, IsNil) 608 c.Assert(ok, Equals, true) 609 610 toResolve, err = pool.ToResolve() 611 c.Assert(err, IsNil) 612 c.Assert(toResolve, HasLen, 0) 613 614 c.Check(pool.Err("one"), IsNil) 615 } 616 617 func (s *poolSuite) TestUpdate(c *C) { 618 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 619 assertstest.AddMany(s.db, s.dev1Acct, s.decl1, s.rev1_1111) 620 assertstest.AddMany(s.db, s.dev2Acct, s.decl2, s.rev2_2222) 621 622 pool := asserts.NewPool(s.db, 64) 623 624 err := pool.AddToUpdate(s.decl1.Ref(), "for_one") // group num: 0 625 c.Assert(err, IsNil) 626 err = pool.AddToUpdate(s.decl2.Ref(), "for_two") // group num: 1 627 c.Assert(err, IsNil) 628 629 storeKeyAt := s.hub.StoreAccountKey("").At() 630 631 toResolve, err := pool.ToResolve() 632 c.Assert(err, IsNil) 633 sortToResolve(toResolve) 634 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 635 asserts.MakePoolGrouping(0, 1): {storeKeyAt}, 636 asserts.MakePoolGrouping(0): {s.dev1Acct.At(), s.decl1.At()}, 637 asserts.MakePoolGrouping(1): {s.dev2Acct.At(), s.decl2.At()}, 638 }) 639 640 ok, err := pool.Add(s.decl1_1, asserts.MakePoolGrouping(0)) 641 c.Assert(err, IsNil) 642 c.Assert(ok, Equals, true) 643 644 toResolve, err = pool.ToResolve() 645 c.Assert(err, IsNil) 646 c.Check(toResolve, HasLen, 0) 647 648 at2222 := &asserts.AtRevision{ 649 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"2222"}}, 650 Revision: asserts.RevisionNotKnown, 651 } 652 err = pool.AddUnresolved(at2222, "for_two") 653 c.Assert(err, IsNil) 654 655 toResolve, err = pool.ToResolve() 656 c.Assert(err, IsNil) 657 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 658 asserts.MakePoolGrouping(1): {&asserts.AtRevision{ 659 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"2222"}}, 660 Revision: 0, 661 }}, 662 }) 663 664 c.Check(pool.Err("for_one"), IsNil) 665 c.Check(pool.Err("for_two"), IsNil) 666 } 667 668 var errBoom = errors.New("boom") 669 670 func (s *poolSuite) TestAddErrorEarly(c *C) { 671 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 672 673 pool := asserts.NewPool(s.db, 64) 674 675 storeKey := s.hub.StoreAccountKey("") 676 err := pool.AddToUpdate(storeKey.Ref(), "store_key") 677 c.Assert(err, IsNil) 678 679 at1111 := &asserts.AtRevision{ 680 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 681 Revision: asserts.RevisionNotKnown, 682 } 683 err = pool.AddUnresolved(at1111, "for_one") 684 c.Assert(err, IsNil) 685 686 toResolve, err := pool.ToResolve() 687 c.Assert(err, IsNil) 688 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 689 asserts.MakePoolGrouping(0): {storeKey.At()}, 690 asserts.MakePoolGrouping(1): {at1111}, 691 }) 692 693 err = pool.AddError(errBoom, storeKey.Ref()) 694 c.Assert(err, IsNil) 695 696 ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1)) 697 c.Assert(err, IsNil) 698 c.Assert(ok, Equals, true) 699 700 toResolve, err = pool.ToResolve() 701 c.Assert(err, IsNil) 702 c.Check(toResolve, HasLen, 0) 703 704 c.Check(pool.Err("store_key"), Equals, errBoom) 705 c.Check(pool.Err("for_one"), Equals, errBoom) 706 } 707 708 func (s *poolSuite) TestAddErrorLater(c *C) { 709 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 710 711 pool := asserts.NewPool(s.db, 64) 712 713 storeKey := s.hub.StoreAccountKey("") 714 err := pool.AddToUpdate(storeKey.Ref(), "store_key") 715 c.Assert(err, IsNil) 716 717 at1111 := &asserts.AtRevision{ 718 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 719 Revision: asserts.RevisionNotKnown, 720 } 721 err = pool.AddUnresolved(at1111, "for_one") 722 c.Assert(err, IsNil) 723 724 toResolve, err := pool.ToResolve() 725 c.Assert(err, IsNil) 726 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 727 asserts.MakePoolGrouping(0): {storeKey.At()}, 728 asserts.MakePoolGrouping(1): {at1111}, 729 }) 730 731 ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1)) 732 c.Assert(err, IsNil) 733 c.Assert(ok, Equals, true) 734 735 err = pool.AddError(errBoom, storeKey.Ref()) 736 c.Assert(err, IsNil) 737 738 toResolve, err = pool.ToResolve() 739 c.Assert(err, IsNil) 740 c.Check(toResolve, HasLen, 0) 741 742 c.Check(pool.Err("store_key"), Equals, errBoom) 743 c.Check(pool.Err("for_one"), Equals, errBoom) 744 } 745 746 func (s *poolSuite) TestNopUpdatePlusFetchOfPushed(c *C) { 747 storeKey := s.hub.StoreAccountKey("") 748 assertstest.AddMany(s.db, storeKey) 749 assertstest.AddMany(s.db, s.dev1Acct) 750 assertstest.AddMany(s.db, s.decl1) 751 assertstest.AddMany(s.db, s.rev1_1111) 752 753 pool := asserts.NewPool(s.db, 64) 754 755 atOne := s.decl1.At() 756 err := pool.AddToUpdate(&atOne.Ref, "for_one") 757 c.Assert(err, IsNil) 758 759 toResolve, err := pool.ToResolve() 760 c.Assert(err, IsNil) 761 sortToResolve(toResolve) 762 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 763 asserts.MakePoolGrouping(0): {storeKey.At(), s.dev1Acct.At(), atOne}, 764 }) 765 766 // no updates but 767 // new push suggestion 768 769 gSuggestion, err := pool.Singleton("suggestion") 770 c.Assert(err, IsNil) 771 772 ok, err := pool.Add(s.rev1_3333, gSuggestion) 773 c.Assert(err, IsNil) 774 c.Assert(ok, Equals, true) 775 776 toResolve, err = pool.ToResolve() 777 c.Assert(err, IsNil) 778 c.Assert(toResolve, HasLen, 0) 779 780 c.Check(pool.Err("for_one"), IsNil) 781 782 pool.AddGroupingError(errBoom, gSuggestion) 783 784 c.Assert(pool.Err("for_one"), IsNil) 785 c.Assert(pool.Err("suggestion"), Equals, errBoom) 786 787 at3333 := s.rev1_3333.At() 788 at3333.Revision = asserts.RevisionNotKnown 789 err = pool.AddUnresolved(at3333, at3333.Unique()) 790 c.Assert(err, IsNil) 791 792 toResolve, err = pool.ToResolve() 793 c.Assert(err, IsNil) 794 c.Assert(toResolve, HasLen, 0) 795 796 err = pool.CommitTo(s.db) 797 c.Check(err, IsNil) 798 799 c.Assert(pool.Err(at3333.Unique()), IsNil) 800 801 a, err := s.rev1_3333.Ref().Resolve(s.db.Find) 802 c.Assert(err, IsNil) 803 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "3333") 804 } 805 806 func (s *poolSuite) TestAddToUpdateThenUnresolved(c *C) { 807 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 808 809 pool := asserts.NewPool(s.db, 64) 810 811 storeKey := s.hub.StoreAccountKey("") 812 storeKeyAt := storeKey.At() 813 storeKeyAt.Revision = asserts.RevisionNotKnown 814 815 err := pool.AddToUpdate(storeKey.Ref(), "for_one") 816 c.Assert(err, IsNil) 817 err = pool.AddUnresolved(storeKeyAt, "for_one") 818 c.Assert(err, IsNil) 819 820 toResolve, err := pool.ToResolve() 821 c.Assert(err, IsNil) 822 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 823 asserts.MakePoolGrouping(0): {storeKey.At()}, 824 }) 825 } 826 827 func (s *poolSuite) TestAddUnresolvedThenToUpdate(c *C) { 828 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 829 830 pool := asserts.NewPool(s.db, 64) 831 832 storeKey := s.hub.StoreAccountKey("") 833 storeKeyAt := storeKey.At() 834 storeKeyAt.Revision = asserts.RevisionNotKnown 835 836 err := pool.AddUnresolved(storeKeyAt, "for_one") 837 c.Assert(err, IsNil) 838 err = pool.AddToUpdate(storeKey.Ref(), "for_one") 839 c.Assert(err, IsNil) 840 841 toResolve, err := pool.ToResolve() 842 c.Assert(err, IsNil) 843 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 844 asserts.MakePoolGrouping(0): {storeKey.At()}, 845 }) 846 } 847 848 func (s *poolSuite) TestNopUpdatePlusFetch(c *C) { 849 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 850 851 pool := asserts.NewPool(s.db, 64) 852 853 storeKey := s.hub.StoreAccountKey("") 854 err := pool.AddToUpdate(storeKey.Ref(), "store_key") 855 c.Assert(err, IsNil) 856 857 at1111 := &asserts.AtRevision{ 858 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 859 Revision: asserts.RevisionNotKnown, 860 } 861 err = pool.AddUnresolved(at1111, "for_one") 862 c.Assert(err, IsNil) 863 864 toResolve, err := pool.ToResolve() 865 c.Assert(err, IsNil) 866 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 867 asserts.MakePoolGrouping(0): {storeKey.At()}, 868 asserts.MakePoolGrouping(1): {at1111}, 869 }) 870 871 ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1)) 872 c.Assert(err, IsNil) 873 c.Assert(ok, Equals, true) 874 875 toResolve, err = pool.ToResolve() 876 c.Assert(err, IsNil) 877 sortToResolve(toResolve) 878 dev1AcctAt := s.dev1Acct.At() 879 dev1AcctAt.Revision = asserts.RevisionNotKnown 880 decl1At := s.decl1.At() 881 decl1At.Revision = asserts.RevisionNotKnown 882 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 883 asserts.MakePoolGrouping(1): {dev1AcctAt, decl1At}, 884 }) 885 886 c.Check(pool.Err("store_key"), IsNil) 887 c.Check(pool.Err("for_one"), IsNil) 888 } 889 890 func (s *poolSuite) TestParallelPartialResolutionFailure(c *C) { 891 pool := asserts.NewPool(s.db, 64) 892 893 atOne := &asserts.AtRevision{ 894 Ref: asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}}, 895 Revision: asserts.RevisionNotKnown, 896 } 897 err := pool.AddUnresolved(atOne, "one") 898 c.Assert(err, IsNil) 899 900 toResolve, err := pool.ToResolve() 901 c.Assert(err, IsNil) 902 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 903 asserts.MakePoolGrouping(0): {atOne}, 904 }) 905 906 ok, err := pool.Add(s.decl1, asserts.MakePoolGrouping(0)) 907 c.Assert(err, IsNil) 908 c.Assert(ok, Equals, true) 909 910 toResolve, err = pool.ToResolve() 911 c.Assert(err, IsNil) 912 sortToResolve(toResolve) 913 dev1AcctAt := s.dev1Acct.At() 914 dev1AcctAt.Revision = asserts.RevisionNotKnown 915 decl1At := s.decl1.At() 916 decl1At.Revision = asserts.RevisionNotKnown 917 storeKeyAt := s.hub.StoreAccountKey("").At() 918 storeKeyAt.Revision = asserts.RevisionNotKnown 919 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 920 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt}, 921 }) 922 923 // failed to get prereqs 924 c.Check(pool.AddGroupingError(errBoom, asserts.MakePoolGrouping(0)), IsNil) 925 926 err = pool.AddUnresolved(atOne, "other") 927 c.Assert(err, IsNil) 928 929 toResolve, err = pool.ToResolve() 930 c.Assert(err, IsNil) 931 c.Check(toResolve, HasLen, 0) 932 933 c.Check(pool.Err("one"), Equals, errBoom) 934 c.Check(pool.Err("other"), IsNil) 935 936 // we fail at commit though 937 err = pool.CommitTo(s.db) 938 c.Check(err, IsNil) 939 c.Check(pool.Err("one"), Equals, errBoom) 940 c.Check(pool.Err("other"), ErrorMatches, "cannot resolve prerequisite assertion.*") 941 } 942 943 func (s *poolSuite) TestAddErrors(c *C) { 944 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 945 946 pool := asserts.NewPool(s.db, 64) 947 948 storeKey := s.hub.StoreAccountKey("") 949 err := pool.AddToUpdate(storeKey.Ref(), "store_key") 950 c.Assert(err, IsNil) 951 952 at1111 := &asserts.AtRevision{ 953 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 954 Revision: asserts.RevisionNotKnown, 955 } 956 err = pool.AddUnresolved(at1111, "for_one") 957 c.Assert(err, IsNil) 958 959 toResolve, err := pool.ToResolve() 960 c.Assert(err, IsNil) 961 c.Check(toResolve, HasLen, 2) 962 963 err = pool.AddError(errBoom, storeKey.Ref()) 964 c.Assert(err, IsNil) 965 966 toResolve, err = pool.ToResolve() 967 c.Assert(err, IsNil) 968 c.Check(toResolve, HasLen, 0) 969 970 c.Check(pool.Errors(), DeepEquals, map[string]error{ 971 "store_key": errBoom, 972 "for_one": asserts.ErrUnresolved, 973 }) 974 } 975 976 func (s *poolSuite) TestPoolReuseWithClearGroupsAndUnchanged(c *C) { 977 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 978 assertstest.AddMany(s.db, s.dev1Acct, s.decl1) 979 assertstest.AddMany(s.db, s.dev2Acct, s.decl2) 980 981 pool := asserts.NewPool(s.db, 64) 982 983 err := pool.AddToUpdate(s.decl1.Ref(), "for_one") // group num: 0 984 c.Assert(err, IsNil) 985 986 storeKeyAt := s.hub.StoreAccountKey("").At() 987 988 toResolve, err := pool.ToResolve() 989 c.Assert(err, IsNil) 990 sortToResolve(toResolve) 991 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 992 asserts.MakePoolGrouping(0): {storeKeyAt, s.dev1Acct.At(), s.decl1.At()}, 993 }) 994 995 ok, err := pool.Add(s.decl1_1, asserts.MakePoolGrouping(0)) 996 c.Assert(err, IsNil) 997 c.Assert(ok, Equals, true) 998 999 toResolve, err = pool.ToResolve() 1000 c.Assert(err, IsNil) 1001 c.Check(toResolve, HasLen, 0) 1002 1003 // clear the groups as we would do for real reuse when we have 1004 // exhausted allowed groups 1005 err = pool.ClearGroups() 1006 c.Assert(err, IsNil) 1007 1008 err = pool.AddToUpdate(s.decl2.Ref(), "for_two") // group num: 0 again 1009 c.Assert(err, IsNil) 1010 1011 // no reference to store key because it is remebered as unchanged 1012 // across the clearing 1013 toResolve, err = pool.ToResolve() 1014 c.Assert(err, IsNil) 1015 sortToResolve(toResolve) 1016 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 1017 asserts.MakePoolGrouping(0): {s.dev2Acct.At(), s.decl2.At()}, 1018 }) 1019 }