gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/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  	seq1_1111r5 *asserts.TestOnlySeq
    49  	seq1_1111r6 *asserts.TestOnlySeq
    50  	seq2_1111r7 *asserts.TestOnlySeq
    51  	seq3_1111r5 *asserts.TestOnlySeq
    52  
    53  	db *asserts.Database
    54  }
    55  
    56  var _ = Suite(&poolSuite{})
    57  
    58  func (s *poolSuite) SetUpTest(c *C) {
    59  	s.BaseTest.SetUpTest(c)
    60  
    61  	s.hub = assertstest.NewStoreStack("hub", nil)
    62  	s.dev1Acct = assertstest.NewAccount(s.hub, "developer1", map[string]interface{}{
    63  		"account-id": "developer1",
    64  	}, "")
    65  	s.dev2Acct = assertstest.NewAccount(s.hub, "developer2", map[string]interface{}{
    66  		"account-id": "developer2",
    67  	}, "")
    68  
    69  	a, err := s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{
    70  		"id":     "one",
    71  		"dev-id": "developer1",
    72  	}, nil, "")
    73  	c.Assert(err, IsNil)
    74  	s.decl1 = a.(*asserts.TestOnlyDecl)
    75  
    76  	a, err = s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{
    77  		"id":       "one",
    78  		"dev-id":   "developer1",
    79  		"revision": "1",
    80  	}, nil, "")
    81  	c.Assert(err, IsNil)
    82  	s.decl1_1 = a.(*asserts.TestOnlyDecl)
    83  
    84  	a, err = s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{
    85  		"id":     "two",
    86  		"dev-id": "developer2",
    87  	}, nil, "")
    88  	c.Assert(err, IsNil)
    89  	s.decl2 = a.(*asserts.TestOnlyDecl)
    90  
    91  	a, err = s.hub.Sign(asserts.TestOnlyRevType, map[string]interface{}{
    92  		"h":      "1111",
    93  		"id":     "one",
    94  		"dev-id": "developer1",
    95  	}, nil, "")
    96  	c.Assert(err, IsNil)
    97  	s.rev1_1111 = a.(*asserts.TestOnlyRev)
    98  
    99  	a, err = s.hub.Sign(asserts.TestOnlyRevType, map[string]interface{}{
   100  		"h":      "3333",
   101  		"id":     "one",
   102  		"dev-id": "developer1",
   103  	}, nil, "")
   104  	c.Assert(err, IsNil)
   105  	s.rev1_3333 = a.(*asserts.TestOnlyRev)
   106  
   107  	a, err = s.hub.Sign(asserts.TestOnlyRevType, map[string]interface{}{
   108  		"h":      "2222",
   109  		"id":     "two",
   110  		"dev-id": "developer2",
   111  	}, nil, "")
   112  	c.Assert(err, IsNil)
   113  	s.rev2_2222 = a.(*asserts.TestOnlyRev)
   114  
   115  	// sequence-forming
   116  
   117  	a, err = s.hub.Sign(asserts.TestOnlySeqType, map[string]interface{}{
   118  		"n":        "1111",
   119  		"sequence": "1",
   120  		"id":       "one",
   121  		"dev-id":   "developer1",
   122  		"revision": "5",
   123  	}, nil, "")
   124  	c.Assert(err, IsNil)
   125  	s.seq1_1111r5 = a.(*asserts.TestOnlySeq)
   126  
   127  	a, err = s.hub.Sign(asserts.TestOnlySeqType, map[string]interface{}{
   128  		"n":        "1111",
   129  		"sequence": "1",
   130  		"id":       "one",
   131  		"dev-id":   "developer1",
   132  		"revision": "6",
   133  	}, nil, "")
   134  	c.Assert(err, IsNil)
   135  	s.seq1_1111r6 = a.(*asserts.TestOnlySeq)
   136  
   137  	a, err = s.hub.Sign(asserts.TestOnlySeqType, map[string]interface{}{
   138  		"n":        "1111",
   139  		"sequence": "2",
   140  		"id":       "one",
   141  		"dev-id":   "developer1",
   142  		"revision": "7",
   143  	}, nil, "")
   144  	c.Assert(err, IsNil)
   145  	s.seq2_1111r7 = a.(*asserts.TestOnlySeq)
   146  
   147  	a, err = s.hub.Sign(asserts.TestOnlySeqType, map[string]interface{}{
   148  		"n":        "1111",
   149  		"sequence": "3",
   150  		"id":       "one",
   151  		"dev-id":   "developer1",
   152  		"revision": "4",
   153  	}, nil, "")
   154  	c.Assert(err, IsNil)
   155  	s.seq3_1111r5 = a.(*asserts.TestOnlySeq)
   156  
   157  	db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
   158  		Backstore: asserts.NewMemoryBackstore(),
   159  		Trusted:   s.hub.Trusted,
   160  	})
   161  	c.Assert(err, IsNil)
   162  	s.db = db
   163  }
   164  
   165  func (s *poolSuite) TestAddUnresolved(c *C) {
   166  	pool := asserts.NewPool(s.db, 64)
   167  
   168  	at1 := &asserts.AtRevision{
   169  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
   170  		Revision: asserts.RevisionNotKnown,
   171  	}
   172  	err := pool.AddUnresolved(at1, "for_one") // group num: 0
   173  	c.Assert(err, IsNil)
   174  
   175  	toResolve, toResolveSeq, err := pool.ToResolve()
   176  	c.Assert(err, IsNil)
   177  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   178  		asserts.MakePoolGrouping(0): {at1},
   179  	})
   180  	c.Check(toResolveSeq, HasLen, 0)
   181  }
   182  
   183  func (s *poolSuite) TestAddUnresolvedPredefined(c *C) {
   184  	pool := asserts.NewPool(s.db, 64)
   185  
   186  	at := s.hub.TrustedAccount.At()
   187  	at.Revision = asserts.RevisionNotKnown
   188  	err := pool.AddUnresolved(at, "for_one")
   189  	c.Assert(err, IsNil)
   190  
   191  	// nothing to resolve
   192  	toResolve, toResolveSeq, err := pool.ToResolve()
   193  	c.Assert(err, IsNil)
   194  	c.Check(toResolve, HasLen, 0)
   195  	c.Check(toResolveSeq, HasLen, 0)
   196  }
   197  
   198  func (s *poolSuite) TestAddUnresolvedGrouping(c *C) {
   199  	pool := asserts.NewPool(s.db, 64)
   200  
   201  	storeKeyAt := s.hub.StoreAccountKey("").At()
   202  
   203  	pool.AddUnresolved(storeKeyAt, "for_two") // group num: 0
   204  	pool.AddUnresolved(storeKeyAt, "for_one") // group num: 1
   205  
   206  	toResolve, toResolveSeq, err := pool.ToResolve()
   207  	c.Assert(err, IsNil)
   208  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   209  		asserts.MakePoolGrouping(0, 1): {storeKeyAt},
   210  	})
   211  	c.Check(toResolveSeq, HasLen, 0)
   212  }
   213  
   214  func (s *poolSuite) TestAddUnresolvedDup(c *C) {
   215  	pool := asserts.NewPool(s.db, 64)
   216  
   217  	storeKeyAt := s.hub.StoreAccountKey("").At()
   218  
   219  	pool.AddUnresolved(storeKeyAt, "for_one") // group num: 0
   220  	pool.AddUnresolved(storeKeyAt, "for_one") // group num: 0
   221  
   222  	toResolve, toResolveSeq, err := pool.ToResolve()
   223  	c.Assert(err, IsNil)
   224  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   225  		asserts.MakePoolGrouping(0): {storeKeyAt},
   226  	})
   227  	c.Check(toResolveSeq, HasLen, 0)
   228  }
   229  
   230  type byAtRevision []*asserts.AtRevision
   231  
   232  func (ats byAtRevision) Len() int {
   233  	return len(ats)
   234  }
   235  
   236  func (ats byAtRevision) Less(i, j int) bool {
   237  	return ats[i].Ref.Unique() < ats[j].Ref.Unique()
   238  }
   239  
   240  func (ats byAtRevision) Swap(i, j int) {
   241  	ats[i], ats[j] = ats[j], ats[i]
   242  }
   243  
   244  func sortToResolve(toResolve map[asserts.Grouping][]*asserts.AtRevision) {
   245  	for _, ats := range toResolve {
   246  		sort.Sort(byAtRevision(ats))
   247  	}
   248  }
   249  
   250  func (s *poolSuite) TestFetch(c *C) {
   251  	pool := asserts.NewPool(s.db, 64)
   252  
   253  	at1111 := &asserts.AtRevision{
   254  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
   255  		Revision: asserts.RevisionNotKnown,
   256  	}
   257  	err := pool.AddUnresolved(at1111, "for_one")
   258  	c.Assert(err, IsNil)
   259  
   260  	toResolve, toResolveSeq, err := pool.ToResolve()
   261  	c.Assert(err, IsNil)
   262  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   263  		asserts.MakePoolGrouping(0): {at1111},
   264  	})
   265  	c.Check(toResolveSeq, HasLen, 0)
   266  
   267  	ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0))
   268  	c.Assert(err, IsNil)
   269  	c.Assert(ok, Equals, true)
   270  
   271  	toResolve, toResolveSeq, err = pool.ToResolve()
   272  	c.Assert(err, IsNil)
   273  	sortToResolve(toResolve)
   274  	dev1AcctAt := s.dev1Acct.At()
   275  	dev1AcctAt.Revision = asserts.RevisionNotKnown
   276  	decl1At := s.decl1.At()
   277  	decl1At.Revision = asserts.RevisionNotKnown
   278  	storeKeyAt := s.hub.StoreAccountKey("").At()
   279  	storeKeyAt.Revision = asserts.RevisionNotKnown
   280  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   281  		asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt, decl1At},
   282  	})
   283  	c.Check(toResolveSeq, HasLen, 0)
   284  
   285  	c.Check(pool.Err("for_one"), IsNil)
   286  }
   287  
   288  func (s *poolSuite) TestFetchSequenceForming(c *C) {
   289  	pool := asserts.NewPool(s.db, 64)
   290  
   291  	// revision and sequence not set
   292  	atseq := &asserts.AtSequence{
   293  		Type:        asserts.TestOnlySeqType,
   294  		SequenceKey: []string{"1111"},
   295  		Revision:    asserts.RevisionNotKnown,
   296  	}
   297  	err := pool.AddUnresolvedSequence(atseq, "for_one")
   298  	c.Assert(err, IsNil)
   299  
   300  	toResolve, toResolveSeq, err := pool.ToResolve()
   301  	c.Assert(err, IsNil)
   302  	c.Check(toResolve, HasLen, 0)
   303  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
   304  		asserts.MakePoolGrouping(0): {atseq},
   305  	})
   306  
   307  	// resolve
   308  	ok, err := pool.Add(s.seq1_1111r5, asserts.MakePoolGrouping(0))
   309  	c.Assert(err, IsNil)
   310  	c.Assert(ok, Equals, true)
   311  
   312  	toResolve, toResolveSeq, err = pool.ToResolve()
   313  	c.Assert(err, IsNil)
   314  
   315  	storeKeyAt := s.hub.StoreAccountKey("").At()
   316  	storeKeyAt.Revision = asserts.RevisionNotKnown
   317  	c.Check(toResolveSeq, HasLen, 0)
   318  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   319  		asserts.MakePoolGrouping(0): {storeKeyAt},
   320  	})
   321  
   322  	ok, err = pool.Add(s.hub.StoreAccountKey(""), asserts.MakePoolGrouping(0))
   323  	c.Assert(err, IsNil)
   324  	c.Assert(ok, Equals, true)
   325  
   326  	c.Check(pool.Err("for_one"), IsNil)
   327  
   328  	err = pool.CommitTo(s.db)
   329  	c.Check(err, IsNil)
   330  	c.Assert(pool.Err("for_one"), IsNil)
   331  }
   332  
   333  func (s *poolSuite) TestCompleteFetch(c *C) {
   334  	pool := asserts.NewPool(s.db, 64)
   335  
   336  	at1111 := &asserts.AtRevision{
   337  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
   338  		Revision: asserts.RevisionNotKnown,
   339  	}
   340  	err := pool.AddUnresolved(at1111, "for_one")
   341  	c.Assert(err, IsNil)
   342  
   343  	toResolve, toResolveSeq, err := pool.ToResolve()
   344  	c.Assert(err, IsNil)
   345  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   346  		asserts.MakePoolGrouping(0): {at1111},
   347  	})
   348  	c.Check(toResolveSeq, HasLen, 0)
   349  
   350  	ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0))
   351  	c.Assert(err, IsNil)
   352  	c.Assert(ok, Equals, true)
   353  
   354  	toResolve, toResolveSeq, err = pool.ToResolve()
   355  	c.Assert(err, IsNil)
   356  	sortToResolve(toResolve)
   357  	dev1AcctAt := s.dev1Acct.At()
   358  	dev1AcctAt.Revision = asserts.RevisionNotKnown
   359  	decl1At := s.decl1.At()
   360  	decl1At.Revision = asserts.RevisionNotKnown
   361  	storeKey := s.hub.StoreAccountKey("")
   362  	storeKeyAt := storeKey.At()
   363  	storeKeyAt.Revision = asserts.RevisionNotKnown
   364  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   365  		asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt, decl1At},
   366  	})
   367  	c.Check(toResolveSeq, HasLen, 0)
   368  
   369  	b := asserts.NewBatch(nil)
   370  	err = b.Add(s.decl1)
   371  	c.Assert(err, IsNil)
   372  	err = b.Add(storeKey)
   373  	c.Assert(err, IsNil)
   374  	err = b.Add(s.dev1Acct)
   375  	c.Assert(err, IsNil)
   376  
   377  	ok, err = pool.AddBatch(b, asserts.MakePoolGrouping(0))
   378  	c.Assert(err, IsNil)
   379  	c.Assert(ok, Equals, true)
   380  
   381  	toResolve, toResolveSeq, err = pool.ToResolve()
   382  	c.Assert(err, IsNil)
   383  	c.Check(toResolve, HasLen, 0)
   384  	c.Check(toResolveSeq, HasLen, 0)
   385  
   386  	c.Check(pool.Err("for_one"), IsNil)
   387  
   388  	err = pool.CommitTo(s.db)
   389  	c.Check(err, IsNil)
   390  	c.Assert(pool.Err("for_one"), IsNil)
   391  
   392  	a, err := at1111.Ref.Resolve(s.db.Find)
   393  	c.Assert(err, IsNil)
   394  	c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111")
   395  }
   396  
   397  func (s *poolSuite) TestPushSuggestionForPrerequisite(c *C) {
   398  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
   399  
   400  	pool := asserts.NewPool(s.db, 64)
   401  
   402  	at1111 := &asserts.AtRevision{
   403  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
   404  		Revision: asserts.RevisionNotKnown,
   405  	}
   406  	err := pool.AddUnresolved(at1111, "for_one")
   407  	c.Assert(err, IsNil)
   408  
   409  	toResolve, toResolveSeq, err := pool.ToResolve()
   410  	c.Assert(err, IsNil)
   411  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   412  		asserts.MakePoolGrouping(0): {at1111},
   413  	})
   414  	c.Check(toResolveSeq, HasLen, 0)
   415  
   416  	ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0))
   417  	c.Assert(err, IsNil)
   418  	c.Assert(ok, Equals, true)
   419  
   420  	// push prerequisite suggestion
   421  	ok, err = pool.Add(s.decl1, asserts.MakePoolGrouping(0))
   422  	c.Assert(err, IsNil)
   423  	c.Assert(ok, Equals, true)
   424  
   425  	toResolve, toResolveSeq, err = pool.ToResolve()
   426  	c.Assert(err, IsNil)
   427  	sortToResolve(toResolve)
   428  	dev1AcctAt := s.dev1Acct.At()
   429  	dev1AcctAt.Revision = asserts.RevisionNotKnown
   430  	storeKey := s.hub.StoreAccountKey("")
   431  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   432  		asserts.MakePoolGrouping(0): {storeKey.At(), dev1AcctAt},
   433  	})
   434  	c.Check(toResolveSeq, HasLen, 0)
   435  
   436  	c.Check(pool.Err("for_one"), IsNil)
   437  
   438  	ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0))
   439  	c.Assert(err, IsNil)
   440  	c.Assert(ok, Equals, true)
   441  
   442  	toResolve, toResolveSeq, err = pool.ToResolve()
   443  	c.Assert(err, IsNil)
   444  	c.Check(toResolve, HasLen, 0)
   445  	c.Check(toResolveSeq, HasLen, 0)
   446  
   447  	c.Check(pool.Err("for_one"), IsNil)
   448  
   449  	err = pool.CommitTo(s.db)
   450  	c.Check(err, IsNil)
   451  	c.Assert(pool.Err("for_one"), IsNil)
   452  
   453  	a, err := at1111.Ref.Resolve(s.db.Find)
   454  	c.Assert(err, IsNil)
   455  	c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111")
   456  }
   457  
   458  func (s *poolSuite) TestPushSuggestionForNew(c *C) {
   459  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
   460  
   461  	pool := asserts.NewPool(s.db, 64)
   462  
   463  	atOne := &asserts.AtRevision{
   464  		Ref:      asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}},
   465  		Revision: asserts.RevisionNotKnown,
   466  	}
   467  	err := pool.AddUnresolved(atOne, "for_one")
   468  	c.Assert(err, IsNil)
   469  
   470  	toResolve, toResolveSeq, err := pool.ToResolve()
   471  	c.Assert(err, IsNil)
   472  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   473  		asserts.MakePoolGrouping(0): {atOne},
   474  	})
   475  	c.Check(toResolveSeq, HasLen, 0)
   476  
   477  	ok, err := pool.Add(s.decl1, asserts.MakePoolGrouping(0))
   478  	c.Assert(err, IsNil)
   479  	c.Assert(ok, Equals, true)
   480  
   481  	// new push suggestion
   482  	ok, err = pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0))
   483  	c.Assert(err, IsNil)
   484  	c.Assert(ok, Equals, true)
   485  
   486  	toResolve, toResolveSeq, err = pool.ToResolve()
   487  	c.Assert(err, IsNil)
   488  	sortToResolve(toResolve)
   489  	dev1AcctAt := s.dev1Acct.At()
   490  	dev1AcctAt.Revision = asserts.RevisionNotKnown
   491  	storeKeyAt := s.hub.StoreAccountKey("").At()
   492  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   493  		asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt},
   494  	})
   495  	c.Check(toResolveSeq, HasLen, 0)
   496  
   497  	c.Check(pool.Err("for_one"), IsNil)
   498  
   499  	ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0))
   500  	c.Assert(err, IsNil)
   501  	c.Assert(ok, Equals, true)
   502  
   503  	toResolve, toResolveSeq, err = pool.ToResolve()
   504  	c.Assert(err, IsNil)
   505  	c.Check(toResolve, HasLen, 0)
   506  	c.Check(toResolveSeq, HasLen, 0)
   507  
   508  	c.Check(pool.Err("for_one"), IsNil)
   509  
   510  	err = pool.CommitTo(s.db)
   511  	c.Check(err, IsNil)
   512  	c.Assert(pool.Err("for_one"), IsNil)
   513  
   514  	a, err := s.rev1_1111.Ref().Resolve(s.db.Find)
   515  	c.Assert(err, IsNil)
   516  	c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111")
   517  }
   518  
   519  func (s *poolSuite) TestPushSuggestionForNewSeqForming(c *C) {
   520  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
   521  
   522  	pool := asserts.NewPool(s.db, 64)
   523  
   524  	atOne := &asserts.AtSequence{
   525  		Type:        asserts.TestOnlySeqType,
   526  		SequenceKey: []string{"1111"},
   527  		Revision:    asserts.RevisionNotKnown,
   528  	}
   529  	err := pool.AddUnresolvedSequence(atOne, "for_one")
   530  	c.Assert(err, IsNil)
   531  
   532  	toResolve, toResolveSeq, err := pool.ToResolve()
   533  	c.Assert(err, IsNil)
   534  	c.Check(toResolve, HasLen, 0)
   535  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
   536  		asserts.MakePoolGrouping(0): {atOne},
   537  	})
   538  
   539  	ok, err := pool.Add(s.seq1_1111r5, asserts.MakePoolGrouping(0))
   540  	c.Assert(err, IsNil)
   541  	c.Assert(ok, Equals, true)
   542  
   543  	// new push suggestion
   544  	ok, err = pool.Add(s.seq2_1111r7, asserts.MakePoolGrouping(0))
   545  	c.Assert(err, IsNil)
   546  	c.Assert(ok, Equals, true)
   547  
   548  	toResolve, toResolveSeq, err = pool.ToResolve()
   549  	c.Assert(err, IsNil)
   550  	sortToResolve(toResolve)
   551  	dev1AcctAt := s.dev1Acct.At()
   552  	dev1AcctAt.Revision = asserts.RevisionNotKnown
   553  
   554  	c.Check(toResolve, HasLen, 1)
   555  	c.Check(toResolveSeq, HasLen, 0)
   556  
   557  	c.Check(pool.Err("for_one"), IsNil)
   558  
   559  	err = pool.CommitTo(s.db)
   560  	c.Check(err, IsNil)
   561  	c.Assert(pool.Err("for_one"), IsNil)
   562  
   563  	a, err := s.seq2_1111r7.Ref().Resolve(s.db.Find)
   564  	c.Assert(err, IsNil)
   565  	c.Check(a.(*asserts.TestOnlySeq).N(), Equals, "1111")
   566  	c.Check(a.Revision(), Equals, 7)
   567  }
   568  
   569  func (s *poolSuite) TestPushSuggestionForNewViaBatch(c *C) {
   570  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
   571  
   572  	pool := asserts.NewPool(s.db, 64)
   573  
   574  	atOne := &asserts.AtRevision{
   575  		Ref:      asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}},
   576  		Revision: asserts.RevisionNotKnown,
   577  	}
   578  	err := pool.AddUnresolved(atOne, "for_one")
   579  	c.Assert(err, IsNil)
   580  
   581  	toResolve, toResolveSeq, err := pool.ToResolve()
   582  	c.Assert(err, IsNil)
   583  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   584  		asserts.MakePoolGrouping(0): {atOne},
   585  	})
   586  	c.Check(toResolveSeq, HasLen, 0)
   587  
   588  	b := asserts.NewBatch(nil)
   589  	err = b.Add(s.decl1)
   590  	c.Assert(err, IsNil)
   591  
   592  	// new push suggestions
   593  	err = b.Add(s.rev1_1111)
   594  	c.Assert(err, IsNil)
   595  	err = b.Add(s.rev1_3333)
   596  	c.Assert(err, IsNil)
   597  
   598  	ok, err := pool.AddBatch(b, asserts.MakePoolGrouping(0))
   599  	c.Assert(err, IsNil)
   600  	c.Assert(ok, Equals, true)
   601  
   602  	toResolve, toResolveSeq, err = pool.ToResolve()
   603  	c.Assert(err, IsNil)
   604  	sortToResolve(toResolve)
   605  	dev1AcctAt := s.dev1Acct.At()
   606  	dev1AcctAt.Revision = asserts.RevisionNotKnown
   607  	storeKeyAt := s.hub.StoreAccountKey("").At()
   608  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   609  		asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt},
   610  	})
   611  	c.Check(toResolveSeq, HasLen, 0)
   612  
   613  	c.Check(pool.Err("for_one"), IsNil)
   614  
   615  	ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0))
   616  	c.Assert(err, IsNil)
   617  	c.Assert(ok, Equals, true)
   618  
   619  	toResolve, toResolveSeq, err = pool.ToResolve()
   620  	c.Assert(err, IsNil)
   621  	c.Check(toResolve, HasLen, 0)
   622  	c.Check(toResolveSeq, HasLen, 0)
   623  
   624  	c.Check(pool.Err("for_one"), IsNil)
   625  
   626  	err = pool.CommitTo(s.db)
   627  	c.Check(err, IsNil)
   628  	c.Assert(pool.Err("for_one"), IsNil)
   629  
   630  	a, err := s.rev1_1111.Ref().Resolve(s.db.Find)
   631  	c.Assert(err, IsNil)
   632  	c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "1111")
   633  
   634  	a, err = s.rev1_3333.Ref().Resolve(s.db.Find)
   635  	c.Assert(err, IsNil)
   636  	c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "3333")
   637  }
   638  
   639  func (s *poolSuite) TestAddUnresolvedUnresolved(c *C) {
   640  	pool := asserts.NewPool(s.db, 64)
   641  
   642  	at1 := &asserts.AtRevision{
   643  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
   644  		Revision: asserts.RevisionNotKnown,
   645  	}
   646  	err := pool.AddUnresolved(at1, "for_one")
   647  	c.Assert(err, IsNil)
   648  
   649  	toResolve, toResolveSeq, err := pool.ToResolve()
   650  	c.Assert(err, IsNil)
   651  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   652  		asserts.MakePoolGrouping(0): {at1},
   653  	})
   654  	c.Check(toResolveSeq, HasLen, 0)
   655  
   656  	toResolve, toResolveSeq, err = pool.ToResolve()
   657  	c.Assert(err, IsNil)
   658  	c.Check(toResolve, HasLen, 0)
   659  	c.Check(toResolveSeq, HasLen, 0)
   660  
   661  	c.Check(pool.Err("for_one"), Equals, asserts.ErrUnresolved)
   662  }
   663  
   664  func (s *poolSuite) TestAddFormatTooNew(c *C) {
   665  	pool := asserts.NewPool(s.db, 64)
   666  
   667  	_, _, err := pool.ToResolve()
   668  	c.Assert(err, IsNil)
   669  
   670  	var a asserts.Assertion
   671  	(func() {
   672  		restore := asserts.MockMaxSupportedFormat(asserts.TestOnlyDeclType, 2)
   673  		defer restore()
   674  
   675  		a, err = s.hub.Sign(asserts.TestOnlyDeclType, map[string]interface{}{
   676  			"id":     "three",
   677  			"dev-id": "developer1",
   678  			"format": "2",
   679  		}, nil, "")
   680  		c.Assert(err, IsNil)
   681  	})()
   682  
   683  	gSuggestion, err := pool.Singleton("suggestion")
   684  	c.Assert(err, IsNil)
   685  
   686  	ok, err := pool.Add(a, gSuggestion)
   687  	c.Check(err, IsNil)
   688  	c.Check(ok, Equals, false)
   689  	c.Assert(pool.Err("suggestion"), ErrorMatches, `proposed "test-only-decl" assertion has format 2 but 0 is latest supported`)
   690  }
   691  
   692  func (s *poolSuite) TestAddOlderIgnored(c *C) {
   693  	pool := asserts.NewPool(s.db, 64)
   694  
   695  	_, _, err := pool.ToResolve()
   696  	c.Assert(err, IsNil)
   697  
   698  	gSuggestion, err := pool.Singleton("suggestion")
   699  	c.Assert(err, IsNil)
   700  
   701  	ok, err := pool.Add(s.decl1_1, gSuggestion)
   702  	c.Assert(err, IsNil)
   703  	c.Assert(ok, Equals, true)
   704  
   705  	ok, err = pool.Add(s.decl1, gSuggestion)
   706  	c.Assert(err, IsNil)
   707  	c.Assert(ok, Equals, true)
   708  
   709  	toResolve, toResolveSeq, err := pool.ToResolve()
   710  	c.Assert(err, IsNil)
   711  	sortToResolve(toResolve)
   712  	dev1AcctAt := s.dev1Acct.At()
   713  	dev1AcctAt.Revision = asserts.RevisionNotKnown
   714  	storeKeyAt := s.hub.StoreAccountKey("").At()
   715  	storeKeyAt.Revision = asserts.RevisionNotKnown
   716  
   717  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   718  		gSuggestion: {storeKeyAt, dev1AcctAt},
   719  	})
   720  	c.Check(toResolveSeq, HasLen, 0)
   721  }
   722  
   723  func (s *poolSuite) TestUnknownGroup(c *C) {
   724  	pool := asserts.NewPool(s.db, 64)
   725  
   726  	_, err := pool.Singleton("suggestion")
   727  	c.Assert(err, IsNil)
   728  	// sanity
   729  	c.Check(pool.Err("suggestion"), IsNil)
   730  
   731  	c.Check(pool.Err("foo"), Equals, asserts.ErrUnknownPoolGroup)
   732  }
   733  
   734  func (s *poolSuite) TestAddCurrentRevision(c *C) {
   735  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.dev1Acct, s.decl1)
   736  
   737  	pool := asserts.NewPool(s.db, 64)
   738  
   739  	atDev1Acct := s.dev1Acct.At()
   740  	atDev1Acct.Revision = asserts.RevisionNotKnown
   741  	err := pool.AddUnresolved(atDev1Acct, "one")
   742  	c.Assert(err, IsNil)
   743  
   744  	atDecl1 := s.decl1.At()
   745  	atDecl1.Revision = asserts.RevisionNotKnown
   746  	err = pool.AddUnresolved(atDecl1, "one")
   747  	c.Assert(err, IsNil)
   748  
   749  	toResolve, toResolveSeq, err := pool.ToResolve()
   750  	c.Assert(err, IsNil)
   751  	sortToResolve(toResolve)
   752  
   753  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   754  		asserts.MakePoolGrouping(0): {s.dev1Acct.At(), s.decl1.At()},
   755  	})
   756  	c.Check(toResolveSeq, HasLen, 0)
   757  
   758  	// re-adding of current revisions, is not what we expect
   759  	// but needs to not produce unnecessary roundtrips
   760  
   761  	ok, err := pool.Add(s.hub.StoreAccountKey(""), asserts.MakePoolGrouping(0))
   762  	c.Assert(err, IsNil)
   763  	c.Assert(ok, Equals, true)
   764  
   765  	// this will be kept marked as unresolved until the ToResolve
   766  	ok, err = pool.Add(s.dev1Acct, asserts.MakePoolGrouping(0))
   767  	c.Assert(err, IsNil)
   768  	c.Assert(ok, Equals, true)
   769  
   770  	ok, err = pool.Add(s.decl1_1, asserts.MakePoolGrouping(0))
   771  	c.Assert(err, IsNil)
   772  	c.Assert(ok, Equals, true)
   773  
   774  	toResolve, toResolveSeq, err = pool.ToResolve()
   775  	c.Assert(err, IsNil)
   776  	c.Assert(toResolve, HasLen, 0)
   777  	c.Assert(toResolveSeq, HasLen, 0)
   778  
   779  	c.Check(pool.Err("one"), IsNil)
   780  }
   781  
   782  func (s *poolSuite) TestAddCurrentRevisionSeqForming(c *C) {
   783  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.dev1Acct, s.decl1)
   784  
   785  	pool := asserts.NewPool(s.db, 64)
   786  
   787  	atSeq := &asserts.AtSequence{
   788  		Type:        asserts.TestOnlySeqType,
   789  		SequenceKey: []string{"1111"},
   790  		Revision:    asserts.RevisionNotKnown,
   791  	}
   792  	err := pool.AddUnresolvedSequence(atSeq, "one")
   793  	c.Assert(err, IsNil)
   794  
   795  	toResolve, toResolveSeq, err := pool.ToResolve()
   796  	c.Assert(err, IsNil)
   797  
   798  	c.Check(toResolve, HasLen, 0)
   799  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
   800  		asserts.MakePoolGrouping(0): {
   801  			&asserts.AtSequence{
   802  				Type:        s.seq1_1111r5.Type(),
   803  				SequenceKey: []string{"1111"},
   804  				Revision:    asserts.RevisionNotKnown,
   805  			}},
   806  	})
   807  
   808  	// re-adding of current revisions, is not what we expect
   809  	// but needs to not produce unnecessary roundtrips
   810  
   811  	ok, err := pool.Add(s.hub.StoreAccountKey(""), asserts.MakePoolGrouping(0))
   812  	c.Assert(err, IsNil)
   813  	c.Assert(ok, Equals, true)
   814  
   815  	// this will be kept marked as unresolved until the ToResolve
   816  	ok, err = pool.Add(s.seq1_1111r5, asserts.MakePoolGrouping(0))
   817  	c.Assert(err, IsNil)
   818  	c.Assert(ok, Equals, true)
   819  
   820  	toResolve, toResolveSeq, err = pool.ToResolve()
   821  	c.Assert(err, IsNil)
   822  	c.Assert(toResolve, HasLen, 0)
   823  	c.Assert(toResolveSeq, HasLen, 0)
   824  
   825  	c.Check(pool.Err("one"), IsNil)
   826  }
   827  
   828  func (s *poolSuite) TestUpdate(c *C) {
   829  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
   830  	assertstest.AddMany(s.db, s.dev1Acct, s.decl1, s.rev1_1111)
   831  	assertstest.AddMany(s.db, s.dev2Acct, s.decl2, s.rev2_2222)
   832  
   833  	pool := asserts.NewPool(s.db, 64)
   834  
   835  	err := pool.AddToUpdate(s.decl1.Ref(), "for_one") // group num: 0
   836  	c.Assert(err, IsNil)
   837  	err = pool.AddToUpdate(s.decl2.Ref(), "for_two") // group num: 1
   838  	c.Assert(err, IsNil)
   839  
   840  	storeKeyAt := s.hub.StoreAccountKey("").At()
   841  
   842  	toResolve, toResolveSeq, err := pool.ToResolve()
   843  	c.Assert(err, IsNil)
   844  	sortToResolve(toResolve)
   845  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   846  		asserts.MakePoolGrouping(0, 1): {storeKeyAt},
   847  		asserts.MakePoolGrouping(0):    {s.dev1Acct.At(), s.decl1.At()},
   848  		asserts.MakePoolGrouping(1):    {s.dev2Acct.At(), s.decl2.At()},
   849  	})
   850  	c.Check(toResolveSeq, HasLen, 0)
   851  
   852  	ok, err := pool.Add(s.decl1_1, asserts.MakePoolGrouping(0))
   853  	c.Assert(err, IsNil)
   854  	c.Assert(ok, Equals, true)
   855  
   856  	toResolve, toResolveSeq, err = pool.ToResolve()
   857  	c.Assert(err, IsNil)
   858  	c.Check(toResolve, HasLen, 0)
   859  	c.Check(toResolveSeq, HasLen, 0)
   860  
   861  	at2222 := &asserts.AtRevision{
   862  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"2222"}},
   863  		Revision: asserts.RevisionNotKnown,
   864  	}
   865  	err = pool.AddUnresolved(at2222, "for_two")
   866  	c.Assert(err, IsNil)
   867  
   868  	toResolve, toResolveSeq, err = pool.ToResolve()
   869  	c.Assert(err, IsNil)
   870  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   871  		asserts.MakePoolGrouping(1): {&asserts.AtRevision{
   872  			Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"2222"}},
   873  			Revision: 0,
   874  		}},
   875  	})
   876  	c.Check(toResolveSeq, HasLen, 0)
   877  
   878  	c.Check(pool.Err("for_one"), IsNil)
   879  	c.Check(pool.Err("for_two"), IsNil)
   880  }
   881  
   882  func (s *poolSuite) TestUpdateSeqFormingUnpinnedNewerSequence(c *C) {
   883  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
   884  
   885  	pool := asserts.NewPool(s.db, 64)
   886  
   887  	atseq := &asserts.AtSequence{
   888  		Type:        s.seq1_1111r5.Type(),
   889  		SequenceKey: []string{"1111"},
   890  		Sequence:    1,
   891  		Revision:    5,
   892  	}
   893  	err := pool.AddSequenceToUpdate(atseq, "for_one") // group num: 0
   894  	c.Assert(err, IsNil)
   895  
   896  	toResolve, toResolveSeq, err := pool.ToResolve()
   897  	c.Assert(err, IsNil)
   898  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   899  		asserts.MakePoolGrouping(0): {s.hub.StoreAccountKey(s.dev1Acct.SignKeyID()).At()},
   900  	})
   901  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
   902  		asserts.MakePoolGrouping(0): {
   903  			&asserts.AtSequence{
   904  				Type:        s.seq1_1111r5.Type(),
   905  				SequenceKey: []string{"1111"},
   906  				Sequence:    1,
   907  				Revision:    5,
   908  			}},
   909  	})
   910  
   911  	c.Check(pool.Err("for_one"), IsNil)
   912  
   913  	// resolve with sequence 3
   914  	ok, err := pool.Add(s.seq3_1111r5, asserts.MakePoolGrouping(0))
   915  	c.Assert(err, IsNil)
   916  	c.Assert(ok, Equals, true)
   917  
   918  	toResolve, toResolveSeq, err = pool.ToResolve()
   919  	c.Assert(err, IsNil)
   920  
   921  	c.Check(toResolve, HasLen, 0)
   922  	c.Check(toResolveSeq, HasLen, 0)
   923  	c.Check(pool.Err("for_one"), IsNil)
   924  
   925  	err = pool.CommitTo(s.db)
   926  	c.Check(err, IsNil)
   927  	c.Assert(pool.Err("for_one"), IsNil)
   928  
   929  	// sequence point 1, revision 5 is still in the db.
   930  	_, err = s.seq1_1111r5.Ref().Resolve(s.db.Find)
   931  	c.Assert(err, IsNil)
   932  
   933  	// and sequence point 3 revision 5 is in the database.
   934  	_, err = s.seq3_1111r5.Ref().Resolve(s.db.Find)
   935  	c.Assert(err, IsNil)
   936  }
   937  
   938  func (s *poolSuite) TestUpdateSeqFormingUnpinnedSameSequenceNewerRev(c *C) {
   939  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
   940  
   941  	pool := asserts.NewPool(s.db, 64)
   942  
   943  	atseq := &asserts.AtSequence{
   944  		Type:        s.seq1_1111r5.Type(),
   945  		SequenceKey: []string{"1111"},
   946  		Sequence:    1,
   947  		Revision:    5,
   948  	}
   949  	err := pool.AddSequenceToUpdate(atseq, "for_one") // group num: 0
   950  	c.Assert(err, IsNil)
   951  
   952  	toResolve, toResolveSeq, err := pool.ToResolve()
   953  	c.Assert(err, IsNil)
   954  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
   955  		asserts.MakePoolGrouping(0): {s.hub.StoreAccountKey(s.dev1Acct.SignKeyID()).At()},
   956  	})
   957  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
   958  		asserts.MakePoolGrouping(0): {
   959  			&asserts.AtSequence{
   960  				Type:        s.seq1_1111r5.Type(),
   961  				SequenceKey: []string{"1111"},
   962  				Sequence:    1,
   963  				Revision:    5,
   964  			}},
   965  	})
   966  
   967  	c.Check(pool.Err("for_one"), IsNil)
   968  
   969  	// resolve
   970  	ok, err := pool.Add(s.seq1_1111r6, asserts.MakePoolGrouping(0))
   971  	c.Assert(err, IsNil)
   972  	c.Assert(ok, Equals, true)
   973  
   974  	toResolve, toResolveSeq, err = pool.ToResolve()
   975  	c.Assert(err, IsNil)
   976  
   977  	c.Check(toResolve, HasLen, 0)
   978  	c.Check(toResolveSeq, HasLen, 0)
   979  	c.Check(pool.Err("for_one"), IsNil)
   980  
   981  	err = pool.CommitTo(s.db)
   982  	c.Check(err, IsNil)
   983  	c.Assert(pool.Err("for_one"), IsNil)
   984  
   985  	// sequence point 1, revision 5 is still in the database.
   986  	_, err = s.seq1_1111r5.Ref().Resolve(s.db.Find)
   987  	c.Assert(err, IsNil)
   988  
   989  	// and sequence point 1 revision 6 is in the database.
   990  	_, err = s.seq1_1111r6.Ref().Resolve(s.db.Find)
   991  	c.Assert(err, IsNil)
   992  }
   993  
   994  func (s *poolSuite) TestUpdateSeqFormingUnpinnedSameSequenceSameRevNoop(c *C) {
   995  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
   996  
   997  	pool := asserts.NewPool(s.db, 64)
   998  
   999  	atseq := &asserts.AtSequence{
  1000  		Type:        s.seq1_1111r5.Type(),
  1001  		SequenceKey: []string{"1111"},
  1002  		Sequence:    1,
  1003  		Revision:    5,
  1004  	}
  1005  	err := pool.AddSequenceToUpdate(atseq, "for_one") // group num: 0
  1006  	c.Assert(err, IsNil)
  1007  
  1008  	toResolve, toResolveSeq, err := pool.ToResolve()
  1009  	c.Assert(err, IsNil)
  1010  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1011  		asserts.MakePoolGrouping(0): {s.hub.StoreAccountKey(s.dev1Acct.SignKeyID()).At()},
  1012  	})
  1013  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
  1014  		asserts.MakePoolGrouping(0): {
  1015  			&asserts.AtSequence{
  1016  				Type:        s.seq1_1111r5.Type(),
  1017  				SequenceKey: []string{"1111"},
  1018  				Sequence:    1,
  1019  				Revision:    5,
  1020  			}},
  1021  	})
  1022  
  1023  	c.Check(pool.Err("for_one"), IsNil)
  1024  
  1025  	// update with same assertion
  1026  	ok, err := pool.Add(s.seq1_1111r5, asserts.MakePoolGrouping(0))
  1027  	c.Assert(err, IsNil)
  1028  	c.Assert(ok, Equals, true)
  1029  
  1030  	toResolve, toResolveSeq, err = pool.ToResolve()
  1031  	c.Assert(err, IsNil)
  1032  	c.Check(toResolve, HasLen, 0)
  1033  	c.Check(toResolveSeq, HasLen, 0)
  1034  	c.Check(pool.Err("for_one"), IsNil)
  1035  
  1036  	err = pool.CommitTo(s.db)
  1037  	c.Check(err, IsNil)
  1038  	c.Assert(pool.Err("for_one"), IsNil)
  1039  
  1040  	// sequence point 1, revision 5 is still in the database.
  1041  	_, err = s.seq1_1111r5.Ref().Resolve(s.db.Find)
  1042  	c.Assert(err, IsNil)
  1043  }
  1044  
  1045  func (s *poolSuite) TestUpdateSeqFormingPinnedNewerSequenceSameRevisionNoop(c *C) {
  1046  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
  1047  
  1048  	pool := asserts.NewPool(s.db, 64)
  1049  
  1050  	atseq := &asserts.AtSequence{
  1051  		Type:        s.seq1_1111r5.Type(),
  1052  		SequenceKey: []string{"1111"},
  1053  		Sequence:    1,
  1054  		Revision:    5,
  1055  		Pinned:      true,
  1056  	}
  1057  	err := pool.AddSequenceToUpdate(atseq, "for_one") // group num: 0
  1058  	c.Assert(err, IsNil)
  1059  
  1060  	toResolve, toResolveSeq, err := pool.ToResolve()
  1061  	c.Assert(err, IsNil)
  1062  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1063  		asserts.MakePoolGrouping(0): {s.hub.StoreAccountKey(s.dev1Acct.SignKeyID()).At()},
  1064  	})
  1065  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
  1066  		asserts.MakePoolGrouping(0): {
  1067  			&asserts.AtSequence{
  1068  				Type:        s.seq1_1111r5.Type(),
  1069  				SequenceKey: []string{"1111"},
  1070  				Sequence:    1,
  1071  				Revision:    5,
  1072  				Pinned:      true,
  1073  			}},
  1074  	})
  1075  
  1076  	c.Check(pool.Err("for_one"), IsNil)
  1077  
  1078  	// resolve
  1079  	ok, err := pool.Add(s.seq3_1111r5, asserts.MakePoolGrouping(0))
  1080  	c.Assert(err, IsNil)
  1081  	c.Assert(ok, Equals, true)
  1082  
  1083  	toResolve, toResolveSeq, err = pool.ToResolve()
  1084  	c.Assert(err, IsNil)
  1085  	c.Check(toResolve, HasLen, 0)
  1086  	c.Check(toResolveSeq, HasLen, 0)
  1087  	c.Check(pool.Err("for_one"), IsNil)
  1088  
  1089  	err = pool.CommitTo(s.db)
  1090  	c.Check(err, IsNil)
  1091  	c.Assert(pool.Err("for_one"), IsNil)
  1092  
  1093  	// sequence point 1, revision 5 is still the latest.
  1094  	_, err = s.seq1_1111r5.Ref().Resolve(s.db.Find)
  1095  	c.Assert(err, IsNil)
  1096  
  1097  	// and sequence point 3 revision 5 wasn't added to asserts database.
  1098  	_, err = s.seq3_1111r5.Ref().Resolve(s.db.Find)
  1099  	c.Assert(asserts.IsNotFound(err), Equals, true)
  1100  }
  1101  
  1102  func (s *poolSuite) TestUpdateSeqFormingPinnedNewerSequenceNewerRevisionNoop(c *C) {
  1103  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
  1104  
  1105  	pool := asserts.NewPool(s.db, 64)
  1106  
  1107  	atseq := &asserts.AtSequence{
  1108  		Type:        s.seq1_1111r5.Type(),
  1109  		SequenceKey: []string{"1111"},
  1110  		Sequence:    1,
  1111  		Revision:    5,
  1112  		Pinned:      true,
  1113  	}
  1114  	err := pool.AddSequenceToUpdate(atseq, "for_one") // group num: 0
  1115  	c.Assert(err, IsNil)
  1116  
  1117  	toResolve, toResolveSeq, err := pool.ToResolve()
  1118  	c.Assert(err, IsNil)
  1119  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1120  		asserts.MakePoolGrouping(0): {s.hub.StoreAccountKey(s.dev1Acct.SignKeyID()).At()},
  1121  	})
  1122  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
  1123  		asserts.MakePoolGrouping(0): {
  1124  			&asserts.AtSequence{
  1125  				Type:        s.seq1_1111r5.Type(),
  1126  				SequenceKey: []string{"1111"},
  1127  				Sequence:    1,
  1128  				Revision:    5,
  1129  				Pinned:      true,
  1130  			}},
  1131  	})
  1132  
  1133  	c.Check(pool.Err("for_one"), IsNil)
  1134  
  1135  	// resolve
  1136  	ok, err := pool.Add(s.seq2_1111r7, asserts.MakePoolGrouping(0))
  1137  	c.Assert(err, IsNil)
  1138  	c.Assert(ok, Equals, true)
  1139  
  1140  	err = pool.CommitTo(s.db)
  1141  	c.Check(err, IsNil)
  1142  	c.Assert(pool.Err("for_one"), IsNil)
  1143  
  1144  	// sequence point 1, revision 5 is still the latest.
  1145  	_, err = s.seq1_1111r5.Ref().Resolve(s.db.Find)
  1146  	c.Assert(err, IsNil)
  1147  
  1148  	// and sequence point 2 revision 7 wasn't added to asserts database.
  1149  	_, err = s.seq2_1111r7.Ref().Resolve(s.db.Find)
  1150  	c.Assert(asserts.IsNotFound(err), Equals, true)
  1151  }
  1152  
  1153  func (s *poolSuite) TestUpdateSeqFormingPinnedSameSequenceNewerRevision(c *C) {
  1154  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
  1155  	pool := asserts.NewPool(s.db, 64)
  1156  
  1157  	atseq := &asserts.AtSequence{
  1158  		Type:        s.seq1_1111r5.Type(),
  1159  		SequenceKey: []string{"1111"},
  1160  		Sequence:    1,
  1161  		Revision:    5,
  1162  		Pinned:      true,
  1163  	}
  1164  	err := pool.AddSequenceToUpdate(atseq, "for_one") // group num: 0
  1165  	c.Assert(err, IsNil)
  1166  
  1167  	toResolve, toResolveSeq, err := pool.ToResolve()
  1168  	c.Assert(err, IsNil)
  1169  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1170  		asserts.MakePoolGrouping(0): {s.hub.StoreAccountKey(s.dev1Acct.SignKeyID()).At()},
  1171  	})
  1172  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
  1173  		asserts.MakePoolGrouping(0): {
  1174  			&asserts.AtSequence{
  1175  				Type:        s.seq1_1111r5.Type(),
  1176  				SequenceKey: []string{"1111"},
  1177  				Sequence:    1,
  1178  				Revision:    5,
  1179  				Pinned:      true,
  1180  			}},
  1181  	})
  1182  
  1183  	c.Check(pool.Err("for_one"), IsNil)
  1184  
  1185  	// resolve
  1186  	ok, err := pool.Add(s.seq1_1111r6, asserts.MakePoolGrouping(0))
  1187  	c.Assert(err, IsNil)
  1188  	c.Assert(ok, Equals, true)
  1189  
  1190  	err = pool.CommitTo(s.db)
  1191  	c.Check(err, IsNil)
  1192  	c.Assert(pool.Err("for_one"), IsNil)
  1193  
  1194  	// sequence point 1, revision 6 is in db.
  1195  	_, err = s.seq1_1111r6.Ref().Resolve(s.db.Find)
  1196  	c.Assert(err, IsNil)
  1197  }
  1198  
  1199  func (s *poolSuite) TestUpdateSeqFormingUseAssertRevision(c *C) {
  1200  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
  1201  
  1202  	pool := asserts.NewPool(s.db, 64)
  1203  
  1204  	atseq := &asserts.AtSequence{
  1205  		Type:        s.seq1_1111r5.Type(),
  1206  		SequenceKey: []string{"1111"},
  1207  		Sequence:    1,
  1208  		Revision:    0, // intentionaly unset
  1209  	}
  1210  	err := pool.AddSequenceToUpdate(atseq, "for_one") // group num: 0
  1211  	c.Assert(err, IsNil)
  1212  
  1213  	toResolve, toResolveSeq, err := pool.ToResolve()
  1214  	c.Assert(err, IsNil)
  1215  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1216  		asserts.MakePoolGrouping(0): {s.hub.StoreAccountKey(s.dev1Acct.SignKeyID()).At()},
  1217  	})
  1218  
  1219  	// verify that revision number from the existing assertion to update was used.
  1220  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
  1221  		asserts.MakePoolGrouping(0): {
  1222  			&asserts.AtSequence{
  1223  				Type:        s.seq1_1111r5.Type(),
  1224  				SequenceKey: []string{"1111"},
  1225  				Sequence:    1,
  1226  				Revision:    5,
  1227  			}},
  1228  	})
  1229  }
  1230  
  1231  func (s *poolSuite) TestAddSequenceToUpdateMissingSequenceError(c *C) {
  1232  	pool := asserts.NewPool(s.db, 64)
  1233  	atseq := &asserts.AtSequence{
  1234  		Type:        s.seq1_1111r5.Type(),
  1235  		SequenceKey: []string{"1111"},
  1236  		Revision:    asserts.RevisionNotKnown,
  1237  	}
  1238  	err := pool.AddSequenceToUpdate(atseq, "for_one")
  1239  	c.Assert(err, ErrorMatches, `internal error: sequence to update must have a sequence number set`)
  1240  }
  1241  
  1242  func (s *poolSuite) TestAddUnresolvedSeqUnresolved(c *C) {
  1243  	pool := asserts.NewPool(s.db, 64)
  1244  
  1245  	atseq := &asserts.AtSequence{
  1246  		Type:        s.seq1_1111r5.Type(),
  1247  		SequenceKey: []string{"1111"},
  1248  		Revision:    asserts.RevisionNotKnown,
  1249  		Sequence:    1,
  1250  	}
  1251  	err := pool.AddUnresolvedSequence(atseq, "for_one")
  1252  	c.Assert(err, IsNil)
  1253  
  1254  	toResolve, toResolveSeq, err := pool.ToResolve()
  1255  	c.Assert(err, IsNil)
  1256  	c.Check(toResolve, HasLen, 0)
  1257  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
  1258  		asserts.MakePoolGrouping(0): {
  1259  			&asserts.AtSequence{
  1260  				Type:        s.seq1_1111r5.Type(),
  1261  				SequenceKey: []string{"1111"},
  1262  				Revision:    asserts.RevisionNotKnown,
  1263  				Sequence:    1,
  1264  			}},
  1265  	})
  1266  
  1267  	toResolve, toResolveSeq, err = pool.ToResolve()
  1268  	c.Assert(err, IsNil)
  1269  	c.Check(toResolve, HasLen, 0)
  1270  	c.Check(toResolveSeq, HasLen, 0)
  1271  
  1272  	c.Check(pool.Err("for_one"), Equals, asserts.ErrUnresolved)
  1273  }
  1274  
  1275  func (s *poolSuite) TestAddUnresolvedSeqOnce(c *C) {
  1276  	pool := asserts.NewPool(s.db, 64)
  1277  
  1278  	atseq := &asserts.AtSequence{
  1279  		Type:        s.seq1_1111r5.Type(),
  1280  		SequenceKey: []string{"1111"},
  1281  		Revision:    asserts.RevisionNotKnown,
  1282  		Sequence:    1,
  1283  	}
  1284  	err := pool.AddUnresolvedSequence(atseq, "for_one")
  1285  	c.Assert(err, IsNil)
  1286  
  1287  	atseq.Sequence = 2
  1288  	atseq.Revision = 3
  1289  	err = pool.AddUnresolvedSequence(atseq, "for_one")
  1290  	c.Assert(err, ErrorMatches, `internal error: sequence \[1111\] is already being resolved`)
  1291  }
  1292  
  1293  func (s *poolSuite) TestAddSeqToUpdateOnce(c *C) {
  1294  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.seq1_1111r5)
  1295  	pool := asserts.NewPool(s.db, 64)
  1296  
  1297  	atseq := &asserts.AtSequence{
  1298  		Type:        s.seq1_1111r5.Type(),
  1299  		SequenceKey: []string{"1111"},
  1300  		Revision:    2,
  1301  		Sequence:    1,
  1302  	}
  1303  	err := pool.AddSequenceToUpdate(atseq, "for_one")
  1304  	c.Assert(err, IsNil)
  1305  
  1306  	atseq.Sequence = 3
  1307  	atseq.Revision = 3
  1308  	err = pool.AddSequenceToUpdate(atseq, "for_one")
  1309  	c.Assert(err, ErrorMatches, `internal error: sequence \[1111\] is already being resolved`)
  1310  }
  1311  
  1312  func (s *poolSuite) TestAddSeqToUpdateNotFound(c *C) {
  1313  	pool := asserts.NewPool(s.db, 64)
  1314  
  1315  	atseq := &asserts.AtSequence{
  1316  		Type:        s.seq1_1111r5.Type(),
  1317  		SequenceKey: []string{"1111"},
  1318  		Revision:    2,
  1319  		Sequence:    1,
  1320  	}
  1321  	err := pool.AddSequenceToUpdate(atseq, "for_one")
  1322  	c.Assert(asserts.IsNotFound(err), Equals, true)
  1323  }
  1324  
  1325  var errBoom = errors.New("boom")
  1326  
  1327  func (s *poolSuite) TestAddErrorEarly(c *C) {
  1328  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
  1329  
  1330  	pool := asserts.NewPool(s.db, 64)
  1331  
  1332  	storeKey := s.hub.StoreAccountKey("")
  1333  	err := pool.AddToUpdate(storeKey.Ref(), "store_key")
  1334  	c.Assert(err, IsNil)
  1335  
  1336  	at1111 := &asserts.AtRevision{
  1337  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
  1338  		Revision: asserts.RevisionNotKnown,
  1339  	}
  1340  	err = pool.AddUnresolved(at1111, "for_one")
  1341  	c.Assert(err, IsNil)
  1342  
  1343  	seq1111 := &asserts.AtSequence{
  1344  		Type:        asserts.TestOnlySeqType,
  1345  		SequenceKey: []string{"1111"},
  1346  		Revision:    asserts.RevisionNotKnown,
  1347  	}
  1348  	err = pool.AddUnresolvedSequence(seq1111, "for_two")
  1349  	c.Assert(err, IsNil)
  1350  
  1351  	toResolve, toResolveSeq, err := pool.ToResolve()
  1352  	c.Assert(err, IsNil)
  1353  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1354  		asserts.MakePoolGrouping(0): {storeKey.At()},
  1355  		asserts.MakePoolGrouping(1): {at1111},
  1356  	})
  1357  	c.Check(toResolveSeq, DeepEquals, map[asserts.Grouping][]*asserts.AtSequence{
  1358  		asserts.MakePoolGrouping(2): {seq1111},
  1359  	})
  1360  
  1361  	err = pool.AddError(errBoom, storeKey.Ref())
  1362  	c.Assert(err, IsNil)
  1363  
  1364  	err = pool.AddSequenceError(errBoom, seq1111)
  1365  	c.Assert(err, IsNil)
  1366  
  1367  	ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1))
  1368  	c.Assert(err, IsNil)
  1369  	c.Assert(ok, Equals, true)
  1370  
  1371  	toResolve, toResolveSeq, err = pool.ToResolve()
  1372  	c.Assert(err, IsNil)
  1373  	c.Check(toResolve, HasLen, 0)
  1374  	c.Check(toResolveSeq, HasLen, 0)
  1375  
  1376  	c.Check(pool.Err("store_key"), Equals, errBoom)
  1377  	c.Check(pool.Err("for_one"), Equals, errBoom)
  1378  	c.Check(pool.Err("for_two"), Equals, errBoom)
  1379  }
  1380  
  1381  func (s *poolSuite) TestAddErrorLater(c *C) {
  1382  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
  1383  
  1384  	pool := asserts.NewPool(s.db, 64)
  1385  
  1386  	storeKey := s.hub.StoreAccountKey("")
  1387  	err := pool.AddToUpdate(storeKey.Ref(), "store_key")
  1388  	c.Assert(err, IsNil)
  1389  
  1390  	at1111 := &asserts.AtRevision{
  1391  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
  1392  		Revision: asserts.RevisionNotKnown,
  1393  	}
  1394  	err = pool.AddUnresolved(at1111, "for_one")
  1395  	c.Assert(err, IsNil)
  1396  
  1397  	toResolve, toResolveSeq, err := pool.ToResolve()
  1398  	c.Assert(err, IsNil)
  1399  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1400  		asserts.MakePoolGrouping(0): {storeKey.At()},
  1401  		asserts.MakePoolGrouping(1): {at1111},
  1402  	})
  1403  	c.Check(toResolveSeq, HasLen, 0)
  1404  
  1405  	ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1))
  1406  	c.Assert(err, IsNil)
  1407  	c.Assert(ok, Equals, true)
  1408  
  1409  	err = pool.AddError(errBoom, storeKey.Ref())
  1410  	c.Assert(err, IsNil)
  1411  
  1412  	toResolve, toResolveSeq, err = pool.ToResolve()
  1413  	c.Assert(err, IsNil)
  1414  	c.Check(toResolve, HasLen, 0)
  1415  	c.Check(toResolveSeq, HasLen, 0)
  1416  
  1417  	c.Check(pool.Err("store_key"), Equals, errBoom)
  1418  	c.Check(pool.Err("for_one"), Equals, errBoom)
  1419  }
  1420  
  1421  func (s *poolSuite) TestNopUpdatePlusFetchOfPushed(c *C) {
  1422  	storeKey := s.hub.StoreAccountKey("")
  1423  	assertstest.AddMany(s.db, storeKey)
  1424  	assertstest.AddMany(s.db, s.dev1Acct)
  1425  	assertstest.AddMany(s.db, s.decl1)
  1426  	assertstest.AddMany(s.db, s.rev1_1111)
  1427  
  1428  	pool := asserts.NewPool(s.db, 64)
  1429  
  1430  	atOne := s.decl1.At()
  1431  	err := pool.AddToUpdate(&atOne.Ref, "for_one")
  1432  	c.Assert(err, IsNil)
  1433  
  1434  	toResolve, toResolveSeq, err := pool.ToResolve()
  1435  	c.Assert(err, IsNil)
  1436  	sortToResolve(toResolve)
  1437  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1438  		asserts.MakePoolGrouping(0): {storeKey.At(), s.dev1Acct.At(), atOne},
  1439  	})
  1440  	c.Check(toResolveSeq, HasLen, 0)
  1441  
  1442  	// no updates but
  1443  	// new push suggestion
  1444  
  1445  	gSuggestion, err := pool.Singleton("suggestion")
  1446  	c.Assert(err, IsNil)
  1447  
  1448  	ok, err := pool.Add(s.rev1_3333, gSuggestion)
  1449  	c.Assert(err, IsNil)
  1450  	c.Assert(ok, Equals, true)
  1451  
  1452  	toResolve, toResolveSeq, err = pool.ToResolve()
  1453  	c.Assert(err, IsNil)
  1454  	c.Assert(toResolve, HasLen, 0)
  1455  	c.Check(toResolveSeq, HasLen, 0)
  1456  
  1457  	c.Check(pool.Err("for_one"), IsNil)
  1458  
  1459  	pool.AddGroupingError(errBoom, gSuggestion)
  1460  
  1461  	c.Assert(pool.Err("for_one"), IsNil)
  1462  	c.Assert(pool.Err("suggestion"), Equals, errBoom)
  1463  
  1464  	at3333 := s.rev1_3333.At()
  1465  	at3333.Revision = asserts.RevisionNotKnown
  1466  	err = pool.AddUnresolved(at3333, at3333.Unique())
  1467  	c.Assert(err, IsNil)
  1468  
  1469  	toResolve, toResolveSeq, err = pool.ToResolve()
  1470  	c.Assert(err, IsNil)
  1471  	c.Assert(toResolve, HasLen, 0)
  1472  	c.Check(toResolveSeq, HasLen, 0)
  1473  
  1474  	err = pool.CommitTo(s.db)
  1475  	c.Check(err, IsNil)
  1476  
  1477  	c.Assert(pool.Err(at3333.Unique()), IsNil)
  1478  
  1479  	a, err := s.rev1_3333.Ref().Resolve(s.db.Find)
  1480  	c.Assert(err, IsNil)
  1481  	c.Check(a.(*asserts.TestOnlyRev).H(), Equals, "3333")
  1482  }
  1483  
  1484  func (s *poolSuite) TestAddToUpdateThenUnresolved(c *C) {
  1485  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
  1486  
  1487  	pool := asserts.NewPool(s.db, 64)
  1488  
  1489  	storeKey := s.hub.StoreAccountKey("")
  1490  	storeKeyAt := storeKey.At()
  1491  	storeKeyAt.Revision = asserts.RevisionNotKnown
  1492  
  1493  	err := pool.AddToUpdate(storeKey.Ref(), "for_one")
  1494  	c.Assert(err, IsNil)
  1495  	err = pool.AddUnresolved(storeKeyAt, "for_one")
  1496  	c.Assert(err, IsNil)
  1497  
  1498  	toResolve, toResolveSeq, err := pool.ToResolve()
  1499  	c.Assert(err, IsNil)
  1500  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1501  		asserts.MakePoolGrouping(0): {storeKey.At()},
  1502  	})
  1503  	c.Check(toResolveSeq, HasLen, 0)
  1504  }
  1505  
  1506  func (s *poolSuite) TestAddUnresolvedThenToUpdate(c *C) {
  1507  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
  1508  
  1509  	pool := asserts.NewPool(s.db, 64)
  1510  
  1511  	storeKey := s.hub.StoreAccountKey("")
  1512  	storeKeyAt := storeKey.At()
  1513  	storeKeyAt.Revision = asserts.RevisionNotKnown
  1514  
  1515  	err := pool.AddUnresolved(storeKeyAt, "for_one")
  1516  	c.Assert(err, IsNil)
  1517  	err = pool.AddToUpdate(storeKey.Ref(), "for_one")
  1518  	c.Assert(err, IsNil)
  1519  
  1520  	toResolve, toResolveSeq, err := pool.ToResolve()
  1521  	c.Assert(err, IsNil)
  1522  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1523  		asserts.MakePoolGrouping(0): {storeKey.At()},
  1524  	})
  1525  	c.Check(toResolveSeq, HasLen, 0)
  1526  }
  1527  
  1528  func (s *poolSuite) TestNopUpdatePlusFetch(c *C) {
  1529  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
  1530  
  1531  	pool := asserts.NewPool(s.db, 64)
  1532  
  1533  	storeKey := s.hub.StoreAccountKey("")
  1534  	err := pool.AddToUpdate(storeKey.Ref(), "store_key")
  1535  	c.Assert(err, IsNil)
  1536  
  1537  	at1111 := &asserts.AtRevision{
  1538  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
  1539  		Revision: asserts.RevisionNotKnown,
  1540  	}
  1541  	err = pool.AddUnresolved(at1111, "for_one")
  1542  	c.Assert(err, IsNil)
  1543  
  1544  	toResolve, toResolveSeq, err := pool.ToResolve()
  1545  	c.Assert(err, IsNil)
  1546  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1547  		asserts.MakePoolGrouping(0): {storeKey.At()},
  1548  		asserts.MakePoolGrouping(1): {at1111},
  1549  	})
  1550  	c.Check(toResolveSeq, HasLen, 0)
  1551  
  1552  	ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(1))
  1553  	c.Assert(err, IsNil)
  1554  	c.Assert(ok, Equals, true)
  1555  
  1556  	toResolve, toResolveSeq, err = pool.ToResolve()
  1557  	c.Assert(err, IsNil)
  1558  	sortToResolve(toResolve)
  1559  	dev1AcctAt := s.dev1Acct.At()
  1560  	dev1AcctAt.Revision = asserts.RevisionNotKnown
  1561  	decl1At := s.decl1.At()
  1562  	decl1At.Revision = asserts.RevisionNotKnown
  1563  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1564  		asserts.MakePoolGrouping(1): {dev1AcctAt, decl1At},
  1565  	})
  1566  	c.Check(toResolveSeq, HasLen, 0)
  1567  
  1568  	c.Check(pool.Err("store_key"), IsNil)
  1569  	c.Check(pool.Err("for_one"), IsNil)
  1570  }
  1571  
  1572  func (s *poolSuite) TestParallelPartialResolutionFailure(c *C) {
  1573  	pool := asserts.NewPool(s.db, 64)
  1574  
  1575  	atOne := &asserts.AtRevision{
  1576  		Ref:      asserts.Ref{Type: asserts.TestOnlyDeclType, PrimaryKey: []string{"one"}},
  1577  		Revision: asserts.RevisionNotKnown,
  1578  	}
  1579  	err := pool.AddUnresolved(atOne, "one")
  1580  	c.Assert(err, IsNil)
  1581  
  1582  	toResolve, toResolveSeq, err := pool.ToResolve()
  1583  	c.Assert(err, IsNil)
  1584  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1585  		asserts.MakePoolGrouping(0): {atOne},
  1586  	})
  1587  	c.Check(toResolveSeq, HasLen, 0)
  1588  
  1589  	ok, err := pool.Add(s.decl1, asserts.MakePoolGrouping(0))
  1590  	c.Assert(err, IsNil)
  1591  	c.Assert(ok, Equals, true)
  1592  
  1593  	toResolve, toResolveSeq, err = pool.ToResolve()
  1594  	c.Assert(err, IsNil)
  1595  	sortToResolve(toResolve)
  1596  	dev1AcctAt := s.dev1Acct.At()
  1597  	dev1AcctAt.Revision = asserts.RevisionNotKnown
  1598  	decl1At := s.decl1.At()
  1599  	decl1At.Revision = asserts.RevisionNotKnown
  1600  	storeKeyAt := s.hub.StoreAccountKey("").At()
  1601  	storeKeyAt.Revision = asserts.RevisionNotKnown
  1602  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1603  		asserts.MakePoolGrouping(0): {storeKeyAt, dev1AcctAt},
  1604  	})
  1605  	c.Check(toResolveSeq, HasLen, 0)
  1606  
  1607  	// failed to get prereqs
  1608  	c.Check(pool.AddGroupingError(errBoom, asserts.MakePoolGrouping(0)), IsNil)
  1609  
  1610  	err = pool.AddUnresolved(atOne, "other")
  1611  	c.Assert(err, IsNil)
  1612  
  1613  	toResolve, toResolveSeq, err = pool.ToResolve()
  1614  	c.Assert(err, IsNil)
  1615  	c.Check(toResolve, HasLen, 0)
  1616  	c.Check(toResolveSeq, HasLen, 0)
  1617  
  1618  	c.Check(pool.Err("one"), Equals, errBoom)
  1619  	c.Check(pool.Err("other"), IsNil)
  1620  
  1621  	// we fail at commit though
  1622  	err = pool.CommitTo(s.db)
  1623  	c.Check(err, IsNil)
  1624  	c.Check(pool.Err("one"), Equals, errBoom)
  1625  	c.Check(pool.Err("other"), ErrorMatches, "cannot resolve prerequisite assertion.*")
  1626  }
  1627  
  1628  func (s *poolSuite) TestAddErrors(c *C) {
  1629  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
  1630  
  1631  	pool := asserts.NewPool(s.db, 64)
  1632  
  1633  	storeKey := s.hub.StoreAccountKey("")
  1634  	err := pool.AddToUpdate(storeKey.Ref(), "store_key")
  1635  	c.Assert(err, IsNil)
  1636  
  1637  	at1111 := &asserts.AtRevision{
  1638  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
  1639  		Revision: asserts.RevisionNotKnown,
  1640  	}
  1641  	err = pool.AddUnresolved(at1111, "for_one")
  1642  	c.Assert(err, IsNil)
  1643  
  1644  	seq1111 := &asserts.AtSequence{
  1645  		Type:        asserts.TestOnlySeqType,
  1646  		SequenceKey: []string{"1111"},
  1647  		Revision:    asserts.RevisionNotKnown,
  1648  	}
  1649  	err = pool.AddUnresolvedSequence(seq1111, "for_two")
  1650  	c.Assert(err, IsNil)
  1651  
  1652  	toResolve, toResolveSeq, err := pool.ToResolve()
  1653  	c.Assert(err, IsNil)
  1654  	c.Check(toResolve, HasLen, 2)
  1655  	c.Check(toResolveSeq, HasLen, 1)
  1656  
  1657  	err = pool.AddError(errBoom, storeKey.Ref())
  1658  	c.Assert(err, IsNil)
  1659  
  1660  	toResolve, toResolveSeq, err = pool.ToResolve()
  1661  	c.Assert(err, IsNil)
  1662  	c.Check(toResolve, HasLen, 0)
  1663  	c.Check(toResolveSeq, HasLen, 0)
  1664  
  1665  	c.Check(pool.Errors(), DeepEquals, map[string]error{
  1666  		"store_key": errBoom,
  1667  		"for_one":   asserts.ErrUnresolved,
  1668  		"for_two":   asserts.ErrUnresolved,
  1669  	})
  1670  }
  1671  
  1672  func (s *poolSuite) TestPoolReuseWithClearGroupsAndUnchanged(c *C) {
  1673  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""))
  1674  	assertstest.AddMany(s.db, s.dev1Acct, s.decl1)
  1675  	assertstest.AddMany(s.db, s.dev2Acct, s.decl2)
  1676  
  1677  	pool := asserts.NewPool(s.db, 64)
  1678  
  1679  	err := pool.AddToUpdate(s.decl1.Ref(), "for_one") // group num: 0
  1680  	c.Assert(err, IsNil)
  1681  
  1682  	storeKeyAt := s.hub.StoreAccountKey("").At()
  1683  
  1684  	toResolve, toResolveSeq, err := pool.ToResolve()
  1685  	c.Assert(err, IsNil)
  1686  	sortToResolve(toResolve)
  1687  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1688  		asserts.MakePoolGrouping(0): {storeKeyAt, s.dev1Acct.At(), s.decl1.At()},
  1689  	})
  1690  	c.Check(toResolveSeq, HasLen, 0)
  1691  
  1692  	ok, err := pool.Add(s.decl1_1, asserts.MakePoolGrouping(0))
  1693  	c.Assert(err, IsNil)
  1694  	c.Assert(ok, Equals, true)
  1695  
  1696  	toResolve, toResolveSeq, err = pool.ToResolve()
  1697  	c.Assert(err, IsNil)
  1698  	c.Check(toResolve, HasLen, 0)
  1699  	c.Check(toResolveSeq, HasLen, 0)
  1700  
  1701  	// clear the groups as we would do for real reuse when we have
  1702  	// exhausted allowed groups
  1703  	err = pool.ClearGroups()
  1704  	c.Assert(err, IsNil)
  1705  
  1706  	err = pool.AddToUpdate(s.decl2.Ref(), "for_two") // group num: 0 again
  1707  	c.Assert(err, IsNil)
  1708  
  1709  	// no reference to store key because it is remebered as unchanged
  1710  	// across the clearing
  1711  	toResolve, toResolveSeq, err = pool.ToResolve()
  1712  	c.Assert(err, IsNil)
  1713  	sortToResolve(toResolve)
  1714  	c.Check(toResolve, DeepEquals, map[asserts.Grouping][]*asserts.AtRevision{
  1715  		asserts.MakePoolGrouping(0): {s.dev2Acct.At(), s.decl2.At()},
  1716  	})
  1717  	c.Check(toResolveSeq, HasLen, 0)
  1718  }
  1719  
  1720  func (s *poolSuite) TestBackstore(c *C) {
  1721  	assertstest.AddMany(s.db, s.hub.StoreAccountKey(""), s.dev1Acct)
  1722  	pool := asserts.NewPool(s.db, 64)
  1723  
  1724  	at1111 := &asserts.AtRevision{
  1725  		Ref:      asserts.Ref{Type: asserts.TestOnlyRevType, PrimaryKey: []string{"1111"}},
  1726  		Revision: asserts.RevisionNotKnown,
  1727  	}
  1728  	c.Assert(pool.AddUnresolved(at1111, "for_one"), IsNil)
  1729  	res, _, err := pool.ToResolve()
  1730  	c.Assert(err, IsNil)
  1731  	c.Assert(res, HasLen, 1)
  1732  
  1733  	// resolve (but do not commit)
  1734  	ok, err := pool.Add(s.rev1_1111, asserts.MakePoolGrouping(0))
  1735  	c.Assert(err, IsNil)
  1736  	c.Assert(ok, Equals, true)
  1737  
  1738  	// the assertion should be available via pool's backstore
  1739  	bs := pool.Backstore()
  1740  	c.Assert(bs, NotNil)
  1741  	a, err := bs.Get(s.rev1_1111.Type(), s.rev1_1111.At().PrimaryKey, s.rev1_1111.Type().MaxSupportedFormat())
  1742  	c.Assert(err, IsNil)
  1743  	c.Assert(a, NotNil)
  1744  }