github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/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 err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 216 c.Assert(err, IsNil) 217 218 toResolve, err = pool.ToResolve() 219 c.Assert(err, IsNil) 220 sortToResolve(toResolve) 221 dev1AcctAt := s.dev1Acct.At() 222 dev1AcctAt.Revision = asserts.RevisionNotKnown 223 decl1At := s.decl1.At() 224 decl1At.Revision = asserts.RevisionNotKnown 225 storeKeyAt := s.hub.StoreAccountKey("").At() 226 storeKeyAt.Revision = asserts.RevisionNotKnown 227 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 228 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt, decl1At}, 229 }) 230 231 c.Check(pool.Err("for_one"), IsNil) 232 } 233 234 func (s *poolSuite) TestCompleteFetch(c *C) { 235 pool := asserts.NewPool(s.db, 64) 236 237 at1111 := &asserts.AtRevision{ 238 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 239 Revision: asserts.RevisionNotKnown, 240 } 241 err := pool.AddUnresolved(at1111, "for_one") 242 c.Assert(err, IsNil) 243 244 toResolve, err := pool.ToResolve() 245 c.Assert(err, IsNil) 246 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 247 asserts.MakePoolGrouping(0): {at1111}, 248 }) 249 250 err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 251 c.Assert(err, IsNil) 252 253 toResolve, err = pool.ToResolve() 254 c.Assert(err, IsNil) 255 sortToResolve(toResolve) 256 dev1AcctAt := s.dev1Acct.At() 257 dev1AcctAt.Revision = asserts.RevisionNotKnown 258 decl1At := s.decl1.At() 259 decl1At.Revision = asserts.RevisionNotKnown 260 storeKey := s.hub.StoreAccountKey("") 261 storeKeyAt := storeKey.At() 262 storeKeyAt.Revision = asserts.RevisionNotKnown 263 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 264 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt, decl1At}, 265 }) 266 267 err = pool.Add(s.decl1, asserts.MakePoolGrouping(0)) 268 c.Assert(err, IsNil) 269 270 err = pool.Add(storeKey, asserts.MakePoolGrouping(0)) 271 c.Assert(err, IsNil) 272 273 err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 274 c.Assert(err, IsNil) 275 276 toResolve, err = pool.ToResolve() 277 c.Assert(err, IsNil) 278 c.Check(toResolve, HasLen, 0) 279 280 c.Check(pool.Err("for_one"), IsNil) 281 282 err = pool.CommitTo(s.db) 283 c.Check(err, IsNil) 284 c.Assert(pool.Err("for_one"), IsNil) 285 286 a, err := at1111.Ref.Resolve(s.db.Find) 287 c.Assert(err, IsNil) 288 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111") 289 } 290 291 func (s *poolSuite) TestPushSuggestionForPrerequisite(c *C) { 292 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 293 294 pool := asserts.NewPool(s.db, 64) 295 296 at1111 := &asserts.AtRevision{ 297 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 298 Revision: asserts.RevisionNotKnown, 299 } 300 err := pool.AddUnresolved(at1111, "for_one") 301 c.Assert(err, IsNil) 302 303 toResolve, err := pool.ToResolve() 304 c.Assert(err, IsNil) 305 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 306 asserts.MakePoolGrouping(0): {at1111}, 307 }) 308 309 err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 310 c.Assert(err, IsNil) 311 312 // push prerequisite suggestion 313 err = pool.Add(s.decl1, asserts.MakePoolGrouping(0)) 314 c.Assert(err, IsNil) 315 316 toResolve, err = pool.ToResolve() 317 c.Assert(err, IsNil) 318 sortToResolve(toResolve) 319 dev1AcctAt := s.dev1Acct.At() 320 dev1AcctAt.Revision = asserts.RevisionNotKnown 321 storeKey := s.hub.StoreAccountKey("") 322 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 323 asserts.MakePoolGrouping(0): {storeKey.At(), dev1AcctAt}, 324 }) 325 326 c.Check(pool.Err("for_one"), IsNil) 327 328 err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 329 c.Assert(err, IsNil) 330 331 toResolve, err = pool.ToResolve() 332 c.Assert(err, IsNil) 333 c.Check(toResolve, HasLen, 0) 334 335 c.Check(pool.Err("for_one"), IsNil) 336 337 err = pool.CommitTo(s.db) 338 c.Check(err, IsNil) 339 c.Assert(pool.Err("for_one"), IsNil) 340 341 a, err := at1111.Ref.Resolve(s.db.Find) 342 c.Assert(err, IsNil) 343 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111") 344 } 345 346 func (s *poolSuite) TestPushSuggestionForNew(c *C) { 347 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 348 349 pool := asserts.NewPool(s.db, 64) 350 351 atOne := &asserts.AtRevision{ 352 Ref: asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}}, 353 Revision: asserts.RevisionNotKnown, 354 } 355 err := pool.AddUnresolved(atOne, "for_one") 356 c.Assert(err, IsNil) 357 358 toResolve, err := pool.ToResolve() 359 c.Assert(err, IsNil) 360 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 361 asserts.MakePoolGrouping(0): {atOne}, 362 }) 363 364 err = pool.Add(s.decl1, asserts.MakePoolGrouping(0)) 365 c.Assert(err, IsNil) 366 367 // new push suggestion 368 err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0)) 369 c.Assert(err, IsNil) 370 371 toResolve, err = pool.ToResolve() 372 c.Assert(err, IsNil) 373 sortToResolve(toResolve) 374 dev1AcctAt := s.dev1Acct.At() 375 dev1AcctAt.Revision = asserts.RevisionNotKnown 376 storeKeyAt := s.hub.StoreAccountKey("").At() 377 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 378 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt}, 379 }) 380 381 c.Check(pool.Err("for_one"), IsNil) 382 383 err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 384 c.Assert(err, IsNil) 385 386 toResolve, err = pool.ToResolve() 387 c.Assert(err, IsNil) 388 c.Check(toResolve, HasLen, 0) 389 390 c.Check(pool.Err("for_one"), IsNil) 391 392 err = pool.CommitTo(s.db) 393 c.Check(err, IsNil) 394 c.Assert(pool.Err("for_one"), IsNil) 395 396 a, err := s.rev1_1111.Ref().Resolve(s.db.Find) 397 c.Assert(err, IsNil) 398 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111") 399 } 400 401 func (s *poolSuite) TestAddUnresolvedUnresolved(c *C) { 402 pool := asserts.NewPool(s.db, 64) 403 404 at1 := &asserts.AtRevision{ 405 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 406 Revision: asserts.RevisionNotKnown, 407 } 408 err := pool.AddUnresolved(at1, "for_one") 409 c.Assert(err, IsNil) 410 411 toResolve, err := pool.ToResolve() 412 c.Assert(err, IsNil) 413 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 414 asserts.MakePoolGrouping(0): {at1}, 415 }) 416 417 toResolve, err = pool.ToResolve() 418 c.Assert(err, IsNil) 419 c.Check(toResolve, HasLen, 0) 420 421 c.Check(pool.Err("for_one"), Equals, asserts.ErrUnresolved) 422 } 423 424 func (s *poolSuite) TestAddFormatTooNew(c *C) { 425 pool := asserts.NewPool(s.db, 64) 426 427 _, err := pool.ToResolve() 428 c.Assert(err, IsNil) 429 430 var a asserts.Assertion 431 (func() { 432 restore := asserts.MockMaxSupportedFormat(asserts.TestOnlyDeclType, 2) 433 defer restore() 434 435 a, err = s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{ 436 "id": "three", 437 "dev-id": "developer1", 438 "format": "2", 439 }, nil, "") 440 c.Assert(err, IsNil) 441 })() 442 443 gSuggestion, err := pool.Singleton("suggestion") 444 c.Assert(err, IsNil) 445 446 err = pool.Add(a, gSuggestion) 447 c.Assert(err, ErrorMatches, `proposed "test-only-decl" assertion has format 2 but 0 is latest supported`) 448 } 449 450 func (s *poolSuite) TestAddOlderIgnored(c *C) { 451 pool := asserts.NewPool(s.db, 64) 452 453 _, err := pool.ToResolve() 454 c.Assert(err, IsNil) 455 456 gSuggestion, err := pool.Singleton("suggestion") 457 c.Assert(err, IsNil) 458 459 err = pool.Add(s.decl1_1, gSuggestion) 460 c.Assert(err, IsNil) 461 462 err = pool.Add(s.decl1, gSuggestion) 463 c.Assert(err, IsNil) 464 465 toResolve, err := pool.ToResolve() 466 c.Assert(err, IsNil) 467 sortToResolve(toResolve) 468 dev1AcctAt := s.dev1Acct.At() 469 dev1AcctAt.Revision = asserts.RevisionNotKnown 470 storeKeyAt := s.hub.StoreAccountKey("").At() 471 storeKeyAt.Revision = asserts.RevisionNotKnown 472 473 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 474 gSuggestion: {storeKeyAt, dev1AcctAt}, 475 }) 476 } 477 478 func (s *poolSuite) TestUnknownGroup(c *C) { 479 pool := asserts.NewPool(s.db, 64) 480 481 _, err := pool.Singleton("suggestion") 482 c.Assert(err, IsNil) 483 // sanity 484 c.Check(pool.Err("suggestion"), IsNil) 485 486 c.Check(pool.Err("foo"), Equals, asserts.ErrUnknownPoolGroup) 487 } 488 489 func (s *poolSuite) TestAddCurrentRevision(c *C) { 490 assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.dev1Acct, s.decl1) 491 492 pool := asserts.NewPool(s.db, 64) 493 494 atDev1Acct := s.dev1Acct.At() 495 atDev1Acct.Revision = asserts.RevisionNotKnown 496 err := pool.AddUnresolved(atDev1Acct, "one") 497 c.Assert(err, IsNil) 498 499 atDecl1 := s.decl1.At() 500 atDecl1.Revision = asserts.RevisionNotKnown 501 err = pool.AddUnresolved(atDecl1, "one") 502 c.Assert(err, IsNil) 503 504 toResolve, err := pool.ToResolve() 505 c.Assert(err, IsNil) 506 sortToResolve(toResolve) 507 508 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 509 asserts.MakePoolGrouping(0): {s.dev1Acct.At(), s.decl1.At()}, 510 }) 511 512 // re-adding of current revisions, is not what we expect 513 // but needs not to produce unneeded roundtrips 514 515 err = pool.Add(s.hub.StoreAccountKey(""), asserts.MakePoolGrouping(0)) 516 c.Assert(err, IsNil) 517 518 // this will be kept marked as unresolved until the ToResolve 519 err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0)) 520 c.Assert(err, IsNil) 521 522 err = pool.Add(s.decl1_1, asserts.MakePoolGrouping(0)) 523 c.Assert(err, IsNil) 524 525 toResolve, err = pool.ToResolve() 526 c.Assert(err, IsNil) 527 c.Assert(toResolve, HasLen, 0) 528 529 c.Check(pool.Err("one"), IsNil) 530 } 531 532 func (s *poolSuite) TestUpdate(c *C) { 533 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 534 assertstest.AddMany(s.db, s.dev1Acct, s.decl1, s.rev1_1111) 535 assertstest.AddMany(s.db, s.dev2Acct, s.decl2, s.rev2_2222) 536 537 pool := asserts.NewPool(s.db, 64) 538 539 err := pool.AddToUpdate(s.decl1.Ref(), "for_one") // group num: 0 540 c.Assert(err, IsNil) 541 err = pool.AddToUpdate(s.decl2.Ref(), "for_two") // group num: 1 542 c.Assert(err, IsNil) 543 544 storeKeyAt := s.hub.StoreAccountKey("").At() 545 546 toResolve, err := pool.ToResolve() 547 c.Assert(err, IsNil) 548 sortToResolve(toResolve) 549 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 550 asserts.MakePoolGrouping(0, 1): {storeKeyAt}, 551 asserts.MakePoolGrouping(0): {s.dev1Acct.At(), s.decl1.At()}, 552 asserts.MakePoolGrouping(1): {s.dev2Acct.At(), s.decl2.At()}, 553 }) 554 555 err = pool.Add(s.decl1_1, asserts.MakePoolGrouping(0)) 556 c.Assert(err, IsNil) 557 558 toResolve, err = pool.ToResolve() 559 c.Assert(err, IsNil) 560 c.Check(toResolve, HasLen, 0) 561 562 at2222 := &asserts.AtRevision{ 563 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"2222"}}, 564 Revision: asserts.RevisionNotKnown, 565 } 566 err = pool.AddUnresolved(at2222, "for_two") 567 c.Assert(err, IsNil) 568 569 toResolve, err = pool.ToResolve() 570 c.Assert(err, IsNil) 571 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 572 asserts.MakePoolGrouping(1): {&asserts.AtRevision{ 573 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"2222"}}, 574 Revision: 0, 575 }}, 576 }) 577 578 c.Check(pool.Err("for_one"), IsNil) 579 c.Check(pool.Err("for_two"), IsNil) 580 } 581 582 var errBoom = errors.New("boom") 583 584 func (s *poolSuite) TestAddErrorEarly(c *C) { 585 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 586 587 pool := asserts.NewPool(s.db, 64) 588 589 storeKey := s.hub.StoreAccountKey("") 590 err := pool.AddToUpdate(storeKey.Ref(), "store_key") 591 c.Assert(err, IsNil) 592 593 at1111 := &asserts.AtRevision{ 594 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 595 Revision: asserts.RevisionNotKnown, 596 } 597 err = pool.AddUnresolved(at1111, "for_one") 598 c.Assert(err, IsNil) 599 600 toResolve, err := pool.ToResolve() 601 c.Assert(err, IsNil) 602 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 603 asserts.MakePoolGrouping(0): {storeKey.At()}, 604 asserts.MakePoolGrouping(1): {at1111}, 605 }) 606 607 err = pool.AddError(errBoom, storeKey.Ref()) 608 c.Assert(err, IsNil) 609 610 err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1)) 611 c.Assert(err, IsNil) 612 613 toResolve, err = pool.ToResolve() 614 c.Assert(err, IsNil) 615 c.Check(toResolve, HasLen, 0) 616 617 c.Check(pool.Err("store_key"), Equals, errBoom) 618 c.Check(pool.Err("for_one"), Equals, errBoom) 619 } 620 621 func (s *poolSuite) TestAddErrorLater(c *C) { 622 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 623 624 pool := asserts.NewPool(s.db, 64) 625 626 storeKey := s.hub.StoreAccountKey("") 627 err := pool.AddToUpdate(storeKey.Ref(), "store_key") 628 c.Assert(err, IsNil) 629 630 at1111 := &asserts.AtRevision{ 631 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 632 Revision: asserts.RevisionNotKnown, 633 } 634 err = pool.AddUnresolved(at1111, "for_one") 635 c.Assert(err, IsNil) 636 637 toResolve, err := pool.ToResolve() 638 c.Assert(err, IsNil) 639 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 640 asserts.MakePoolGrouping(0): {storeKey.At()}, 641 asserts.MakePoolGrouping(1): {at1111}, 642 }) 643 644 err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1)) 645 c.Assert(err, IsNil) 646 647 err = pool.AddError(errBoom, storeKey.Ref()) 648 c.Assert(err, IsNil) 649 650 toResolve, err = pool.ToResolve() 651 c.Assert(err, IsNil) 652 c.Check(toResolve, HasLen, 0) 653 654 c.Check(pool.Err("store_key"), Equals, errBoom) 655 c.Check(pool.Err("for_one"), Equals, errBoom) 656 } 657 658 func (s *poolSuite) TestNopUpdatePlusFetchOfPushed(c *C) { 659 storeKey := s.hub.StoreAccountKey("") 660 assertstest.AddMany(s.db, storeKey) 661 assertstest.AddMany(s.db, s.dev1Acct) 662 assertstest.AddMany(s.db, s.decl1) 663 assertstest.AddMany(s.db, s.rev1_1111) 664 665 pool := asserts.NewPool(s.db, 64) 666 667 atOne := s.decl1.At() 668 err := pool.AddToUpdate(&atOne.Ref, "for_one") 669 c.Assert(err, IsNil) 670 671 toResolve, err := pool.ToResolve() 672 c.Assert(err, IsNil) 673 sortToResolve(toResolve) 674 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 675 asserts.MakePoolGrouping(0): {storeKey.At(), s.dev1Acct.At(), atOne}, 676 }) 677 678 // no updates but 679 // new push suggestion 680 681 gSuggestion, err := pool.Singleton("suggestion") 682 c.Assert(err, IsNil) 683 684 err = pool.Add(s.rev1_3333, gSuggestion) 685 c.Assert(err, IsNil) 686 687 toResolve, err = pool.ToResolve() 688 c.Assert(err, IsNil) 689 c.Assert(toResolve, HasLen, 0) 690 691 c.Check(pool.Err("for_one"), IsNil) 692 693 pool.AddGroupingError(errBoom, gSuggestion) 694 695 c.Assert(pool.Err("for_one"), IsNil) 696 c.Assert(pool.Err("suggestion"), Equals, errBoom) 697 698 at3333 := s.rev1_3333.At() 699 at3333.Revision = asserts.RevisionNotKnown 700 err = pool.AddUnresolved(at3333, at3333.Unique()) 701 c.Assert(err, IsNil) 702 703 toResolve, err = pool.ToResolve() 704 c.Assert(err, IsNil) 705 c.Assert(toResolve, HasLen, 0) 706 707 err = pool.CommitTo(s.db) 708 c.Check(err, IsNil) 709 710 c.Assert(pool.Err(at3333.Unique()), IsNil) 711 712 a, err := s.rev1_3333.Ref().Resolve(s.db.Find) 713 c.Assert(err, IsNil) 714 c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "3333") 715 } 716 717 func (s *poolSuite) TestAddToUpdateThenUnresolved(c *C) { 718 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 719 720 pool := asserts.NewPool(s.db, 64) 721 722 storeKey := s.hub.StoreAccountKey("") 723 storeKeyAt := storeKey.At() 724 storeKeyAt.Revision = asserts.RevisionNotKnown 725 726 err := pool.AddToUpdate(storeKey.Ref(), "for_one") 727 c.Assert(err, IsNil) 728 err = pool.AddUnresolved(storeKeyAt, "for_one") 729 c.Assert(err, IsNil) 730 731 toResolve, err := pool.ToResolve() 732 c.Assert(err, IsNil) 733 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 734 asserts.MakePoolGrouping(0): {storeKey.At()}, 735 }) 736 } 737 738 func (s *poolSuite) TestAddUnresolvedThenToUpdate(c *C) { 739 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 740 741 pool := asserts.NewPool(s.db, 64) 742 743 storeKey := s.hub.StoreAccountKey("") 744 storeKeyAt := storeKey.At() 745 storeKeyAt.Revision = asserts.RevisionNotKnown 746 747 err := pool.AddUnresolved(storeKeyAt, "for_one") 748 c.Assert(err, IsNil) 749 err = pool.AddToUpdate(storeKey.Ref(), "for_one") 750 c.Assert(err, IsNil) 751 752 toResolve, err := pool.ToResolve() 753 c.Assert(err, IsNil) 754 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 755 asserts.MakePoolGrouping(0): {storeKey.At()}, 756 }) 757 } 758 759 func (s *poolSuite) TestNopUpdatePlusFetch(c *C) { 760 assertstest.AddMany(s.db, s.hub.StoreAccountKey("")) 761 762 pool := asserts.NewPool(s.db, 64) 763 764 storeKey := s.hub.StoreAccountKey("") 765 err := pool.AddToUpdate(storeKey.Ref(), "store_key") 766 c.Assert(err, IsNil) 767 768 at1111 := &asserts.AtRevision{ 769 Ref: asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}}, 770 Revision: asserts.RevisionNotKnown, 771 } 772 err = pool.AddUnresolved(at1111, "for_one") 773 c.Assert(err, IsNil) 774 775 toResolve, err := pool.ToResolve() 776 c.Assert(err, IsNil) 777 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 778 asserts.MakePoolGrouping(0): {storeKey.At()}, 779 asserts.MakePoolGrouping(1): {at1111}, 780 }) 781 782 err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1)) 783 c.Assert(err, IsNil) 784 785 toResolve, err = pool.ToResolve() 786 c.Assert(err, IsNil) 787 sortToResolve(toResolve) 788 dev1AcctAt := s.dev1Acct.At() 789 dev1AcctAt.Revision = asserts.RevisionNotKnown 790 decl1At := s.decl1.At() 791 decl1At.Revision = asserts.RevisionNotKnown 792 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 793 asserts.MakePoolGrouping(1): {dev1AcctAt, decl1At}, 794 }) 795 796 c.Check(pool.Err("store_key"), IsNil) 797 c.Check(pool.Err("for_one"), IsNil) 798 } 799 800 func (s *poolSuite) TestParallelPartialResolutionFailure(c *C) { 801 pool := asserts.NewPool(s.db, 64) 802 803 atOne := &asserts.AtRevision{ 804 Ref: asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}}, 805 Revision: asserts.RevisionNotKnown, 806 } 807 err := pool.AddUnresolved(atOne, "one") 808 c.Assert(err, IsNil) 809 810 toResolve, err := pool.ToResolve() 811 c.Assert(err, IsNil) 812 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 813 asserts.MakePoolGrouping(0): {atOne}, 814 }) 815 816 err = pool.Add(s.decl1, asserts.MakePoolGrouping(0)) 817 c.Assert(err, IsNil) 818 819 toResolve, err = pool.ToResolve() 820 c.Assert(err, IsNil) 821 sortToResolve(toResolve) 822 dev1AcctAt := s.dev1Acct.At() 823 dev1AcctAt.Revision = asserts.RevisionNotKnown 824 decl1At := s.decl1.At() 825 decl1At.Revision = asserts.RevisionNotKnown 826 storeKeyAt := s.hub.StoreAccountKey("").At() 827 storeKeyAt.Revision = asserts.RevisionNotKnown 828 c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{ 829 asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt}, 830 }) 831 832 // failed to get prereqs 833 c.Check(pool.AddGroupingError(errBoom, asserts.MakePoolGrouping(0)), IsNil) 834 835 err = pool.AddUnresolved(atOne, "other") 836 c.Assert(err, IsNil) 837 838 toResolve, err = pool.ToResolve() 839 c.Assert(err, IsNil) 840 c.Check(toResolve, HasLen, 0) 841 842 c.Check(pool.Err("one"), Equals, errBoom) 843 c.Check(pool.Err("other"), IsNil) 844 845 // we fail at commit though 846 err = pool.CommitTo(s.db) 847 c.Check(err, IsNil) 848 c.Check(pool.Err("one"), Equals, errBoom) 849 c.Check(pool.Err("other"), ErrorMatches, "cannot resolve prerequisite assertion.*") 850 }