Ai
1 Star 0 Fork 1

mysnapcore/mysnapd

forked from tupelo-shen/mysnapd 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
validation_set_tracking_test.go 15.33 KB
一键复制 编辑 原始数据 按行查看 历史
tupelo-shen 提交于 2022-11-08 15:12 +08:00 . fix: overlord commit
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package assertstate_test
import (
. "gopkg.in/check.v1"
"gitee.com/mysnapcore/mysnapd/asserts"
"gitee.com/mysnapcore/mysnapd/asserts/assertstest"
"gitee.com/mysnapcore/mysnapd/overlord/assertstate"
"gitee.com/mysnapcore/mysnapd/overlord/assertstate/assertstatetest"
"gitee.com/mysnapcore/mysnapd/overlord/state"
"gitee.com/mysnapcore/mysnapd/testutil"
)
type validationSetTrackingSuite struct {
st *state.State
dev1Signing *assertstest.SigningDB
dev1acct *asserts.Account
}
var _ = Suite(&validationSetTrackingSuite{})
func (s *validationSetTrackingSuite) SetUpTest(c *C) {
s.st = state.New(nil)
s.st.Lock()
defer s.st.Unlock()
storeSigning := assertstest.NewStoreStack("can0nical", nil)
db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{
Backstore: asserts.NewMemoryBackstore(),
Trusted: storeSigning.Trusted,
})
c.Assert(err, IsNil)
c.Assert(db.Add(storeSigning.StoreAccountKey("")), IsNil)
assertstate.ReplaceDB(s.st, db)
s.dev1acct = assertstest.NewAccount(storeSigning, "developer1", nil, "")
c.Assert(storeSigning.Add(s.dev1acct), IsNil)
dev1PrivKey, _ = assertstest.GenerateKey(752)
acct1Key := assertstest.NewAccountKey(storeSigning, s.dev1acct, nil, dev1PrivKey.PublicKey(), "")
assertstatetest.AddMany(s.st, storeSigning.StoreAccountKey(""), s.dev1acct, acct1Key)
s.dev1Signing = assertstest.NewSigningDB(s.dev1acct.AccountID(), dev1PrivKey)
c.Check(s.dev1Signing, NotNil)
c.Assert(storeSigning.Add(acct1Key), IsNil)
}
func (s *validationSetTrackingSuite) TestUpdate(c *C) {
s.st.Lock()
defer s.st.Unlock()
all, err := assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 0)
tr := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
PinnedAt: 1,
Current: 2,
}
assertstate.UpdateValidationSet(s.st, &tr)
all, err = assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 1)
for k, v := range all {
c.Check(k, Equals, "foo/bar")
c.Check(v, DeepEquals, &assertstate.ValidationSetTracking{AccountID: "foo", Name: "bar", Mode: assertstate.Enforce, PinnedAt: 1, Current: 2})
}
tr = assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "bar",
Mode: assertstate.Monitor,
PinnedAt: 2,
Current: 3,
}
assertstate.UpdateValidationSet(s.st, &tr)
all, err = assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 1)
for k, v := range all {
c.Check(k, Equals, "foo/bar")
c.Check(v, DeepEquals, &assertstate.ValidationSetTracking{AccountID: "foo", Name: "bar", Mode: assertstate.Monitor, PinnedAt: 2, Current: 3})
}
tr = assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "baz",
Mode: assertstate.Enforce,
Current: 3,
}
assertstate.UpdateValidationSet(s.st, &tr)
all, err = assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 2)
var gotFirst, gotSecond bool
for k, v := range all {
if k == "foo/bar" {
gotFirst = true
c.Check(v, DeepEquals, &assertstate.ValidationSetTracking{AccountID: "foo", Name: "bar", Mode: assertstate.Monitor, PinnedAt: 2, Current: 3})
} else {
gotSecond = true
c.Check(k, Equals, "foo/baz")
c.Check(v, DeepEquals, &assertstate.ValidationSetTracking{AccountID: "foo", Name: "baz", Mode: assertstate.Enforce, PinnedAt: 0, Current: 3})
}
}
c.Check(gotFirst, Equals, true)
c.Check(gotSecond, Equals, true)
}
// there is a more extensive test for forget in assertstate_test.go.
func (s *validationSetTrackingSuite) TestForget(c *C) {
s.st.Lock()
defer s.st.Unlock()
// delete non-existing one is fine
assertstate.ForgetValidationSet(s.st, "foo", "bar")
all, err := assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 0)
tr := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "bar",
Mode: assertstate.Monitor,
}
assertstate.UpdateValidationSet(s.st, &tr)
all, err = assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 1)
// forget existing one
assertstate.ForgetValidationSet(s.st, "foo", "bar")
all, err = assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 0)
}
func (s *validationSetTrackingSuite) TestGet(c *C) {
s.st.Lock()
defer s.st.Unlock()
err := assertstate.GetValidationSet(s.st, "foo", "bar", nil)
c.Assert(err, ErrorMatches, `internal error: tr is nil`)
tr := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
Current: 3,
}
assertstate.UpdateValidationSet(s.st, &tr)
var res assertstate.ValidationSetTracking
err = assertstate.GetValidationSet(s.st, "foo", "bar", &res)
c.Assert(err, IsNil)
c.Check(res, DeepEquals, tr)
// non-existing
err = assertstate.GetValidationSet(s.st, "foo", "baz", &res)
c.Assert(err, testutil.ErrorIs, state.ErrNoState)
}
func (s *validationSetTrackingSuite) mockAssert(c *C, name, sequence, presence string) asserts.Assertion {
snaps := []interface{}{map[string]interface{}{
"id": "yOqKhntON3vR7kwEbVPsILm7bUViPDzz",
"name": "snap-b",
"presence": presence,
}}
headers := map[string]interface{}{
"authority-id": s.dev1acct.AccountID(),
"account-id": s.dev1acct.AccountID(),
"name": name,
"series": "16",
"sequence": sequence,
"revision": "5",
"timestamp": "2030-11-06T09:16:26Z",
"snaps": snaps,
}
as, err := s.dev1Signing.Sign(asserts.ValidationSetType, headers, nil, "")
c.Assert(err, IsNil)
return as
}
func (s *validationSetTrackingSuite) TestEnforcedValidationSets(c *C) {
s.st.Lock()
defer s.st.Unlock()
tr := assertstate.ValidationSetTracking{
AccountID: s.dev1acct.AccountID(),
Name: "foo",
Mode: assertstate.Enforce,
Current: 2,
}
assertstate.UpdateValidationSet(s.st, &tr)
tr = assertstate.ValidationSetTracking{
AccountID: s.dev1acct.AccountID(),
Name: "bar",
Mode: assertstate.Enforce,
PinnedAt: 1,
Current: 3,
}
assertstate.UpdateValidationSet(s.st, &tr)
tr = assertstate.ValidationSetTracking{
AccountID: s.dev1acct.AccountID(),
Name: "baz",
Mode: assertstate.Monitor,
Current: 5,
}
assertstate.UpdateValidationSet(s.st, &tr)
vs1 := s.mockAssert(c, "foo", "2", "required")
c.Assert(assertstate.Add(s.st, vs1), IsNil)
vs2 := s.mockAssert(c, "bar", "1", "invalid")
c.Assert(assertstate.Add(s.st, vs2), IsNil)
vs3 := s.mockAssert(c, "baz", "5", "invalid")
c.Assert(assertstate.Add(s.st, vs3), IsNil)
valsets, err := assertstate.TrackedEnforcedValidationSets(s.st)
c.Assert(err, IsNil)
// foo and bar are in conflict, use this as an indirect way of checking
// that both were added to valsets.
// XXX: switch to CheckPresenceInvalid / CheckPresenceRequired once available.
err = valsets.Conflict()
c.Check(err, ErrorMatches, `validation sets are in conflict:\n- cannot constrain snap "snap-b" as both invalid \(.*/bar\) and required at any revision \(.*/foo\)`)
}
func (s *validationSetTrackingSuite) TestEnforcedValidationSetsWithExtraSets(c *C) {
s.st.Lock()
defer s.st.Unlock()
tr := assertstate.ValidationSetTracking{
AccountID: s.dev1acct.AccountID(),
Name: "foo",
Mode: assertstate.Enforce,
Current: 2,
}
assertstate.UpdateValidationSet(s.st, &tr)
tr = assertstate.ValidationSetTracking{
AccountID: s.dev1acct.AccountID(),
Name: "bar",
Mode: assertstate.Enforce,
PinnedAt: 1,
Current: 3,
}
assertstate.UpdateValidationSet(s.st, &tr)
vs1 := s.mockAssert(c, "foo", "2", "optional")
c.Assert(assertstate.Add(s.st, vs1), IsNil)
vs2 := s.mockAssert(c, "bar", "1", "required")
c.Assert(assertstate.Add(s.st, vs2), IsNil)
valsets, err := assertstate.TrackedEnforcedValidationSets(s.st)
c.Assert(err, IsNil)
err = valsets.Conflict()
c.Assert(err, IsNil)
// use extra validation sets that trigger conflicts to verify they are
// considered by EnforcedValidationSets.
// extra validation set "foo" replaces vs from the state
extra1 := s.mockAssert(c, "foo", "9", "required")
valsets, err = assertstate.TrackedEnforcedValidationSets(s.st, extra1.(*asserts.ValidationSet))
c.Assert(err, IsNil)
err = valsets.Conflict()
c.Assert(err, IsNil)
// extra validations set "baz" is not tracked, it augments computed validation sets (and creates a conflict)
extra2 := s.mockAssert(c, "baz", "9", "invalid")
valsets, err = assertstate.TrackedEnforcedValidationSets(s.st, extra1.(*asserts.ValidationSet), extra2.(*asserts.ValidationSet))
c.Assert(err, IsNil)
err = valsets.Conflict()
c.Check(err, ErrorMatches, `validation sets are in conflict:\n- cannot constrain snap "snap-b" as both invalid \(.*/baz\) and required at any revision \(.*/foo\)`)
// extra validations set "baz" is not tracked, it augments computed validation sets (no conflict this time)
extra2 = s.mockAssert(c, "baz", "9", "optional")
valsets, err = assertstate.TrackedEnforcedValidationSets(s.st, extra1.(*asserts.ValidationSet), extra2.(*asserts.ValidationSet))
c.Assert(err, IsNil)
err = valsets.Conflict()
c.Assert(err, IsNil)
// extra validations set replace both foo and bar vs from the state
extra1 = s.mockAssert(c, "foo", "9", "required")
extra2 = s.mockAssert(c, "bar", "9", "invalid")
valsets, err = assertstate.TrackedEnforcedValidationSets(s.st, extra1.(*asserts.ValidationSet), extra2.(*asserts.ValidationSet))
c.Assert(err, IsNil)
err = valsets.Conflict()
c.Check(err, ErrorMatches, `validation sets are in conflict:\n- cannot constrain snap "snap-b" as both invalid \(.*/bar\) and required at any revision \(.*/foo\)`)
// no conflict once both are invalid
extra1 = s.mockAssert(c, "foo", "9", "invalid")
valsets, err = assertstate.TrackedEnforcedValidationSets(s.st, extra1.(*asserts.ValidationSet), extra2.(*asserts.ValidationSet))
c.Assert(err, IsNil)
err = valsets.Conflict()
c.Check(err, IsNil)
}
func (s *validationSetTrackingSuite) TestAddToValidationSetsHistory(c *C) {
s.st.Lock()
defer s.st.Unlock()
all, err := assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 0)
tr1 := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
PinnedAt: 1,
Current: 2,
}
assertstate.UpdateValidationSet(s.st, &tr1)
tr2 := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "baz",
Mode: assertstate.Monitor,
Current: 4,
}
assertstate.UpdateValidationSet(s.st, &tr2)
c.Assert(assertstate.AddCurrentTrackingToValidationSetsHistory(s.st), IsNil)
top, err := assertstate.ValidationSetsHistoryTop(s.st)
c.Assert(err, IsNil)
c.Check(top, DeepEquals, map[string]*assertstate.ValidationSetTracking{
"foo/bar": {
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
PinnedAt: 1,
Current: 2,
},
"foo/baz": {
AccountID: "foo",
Name: "baz",
Mode: assertstate.Monitor,
Current: 4,
},
})
// adding unchanged validation set tracking doesn't create another entry
c.Assert(assertstate.AddCurrentTrackingToValidationSetsHistory(s.st), IsNil)
top2, err := assertstate.ValidationSetsHistoryTop(s.st)
c.Assert(err, IsNil)
c.Check(top, DeepEquals, top2)
vshist, err := assertstate.ValidationSetsHistory(s.st)
c.Assert(err, IsNil)
c.Check(vshist, HasLen, 1)
tr3 := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "boo",
Mode: assertstate.Enforce,
Current: 2,
}
assertstate.UpdateValidationSet(s.st, &tr3)
c.Assert(assertstate.AddCurrentTrackingToValidationSetsHistory(s.st), IsNil)
vshist, err = assertstate.ValidationSetsHistory(s.st)
c.Assert(err, IsNil)
// the history now has 2 entries
c.Check(vshist, HasLen, 2)
top3, err := assertstate.ValidationSetsHistoryTop(s.st)
c.Assert(err, IsNil)
c.Check(top3, DeepEquals, map[string]*assertstate.ValidationSetTracking{
"foo/bar": {
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
PinnedAt: 1,
Current: 2,
},
"foo/baz": {
AccountID: "foo",
Name: "baz",
Mode: assertstate.Monitor,
Current: 4,
},
"foo/boo": {
AccountID: "foo",
Name: "boo",
Mode: assertstate.Enforce,
Current: 2,
},
})
}
func (s *validationSetTrackingSuite) TestAddToValidationSetsHistoryRemovesOldEntries(c *C) {
restore := assertstate.MockMaxValidationSetsHistorySize(4)
defer restore()
s.st.Lock()
defer s.st.Unlock()
all, err := assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 0)
for i := 1; i <= 6; i++ {
tr := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
Current: i,
}
assertstate.UpdateValidationSet(s.st, &tr)
c.Assert(assertstate.AddCurrentTrackingToValidationSetsHistory(s.st), IsNil)
}
vshist, err := assertstate.ValidationSetsHistory(s.st)
c.Assert(err, IsNil)
// two first entries got dropped
c.Check(vshist, DeepEquals, []map[string]*assertstate.ValidationSetTracking{
{
"foo/bar": {
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
Current: 3,
},
},
{
"foo/bar": {
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
Current: 4,
},
},
{
"foo/bar": {
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
Current: 5,
},
},
{
"foo/bar": {
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
Current: 6,
},
},
})
}
func (s *validationSetTrackingSuite) TestRestoreValidationSetsTrackingNoHistory(c *C) {
s.st.Lock()
defer s.st.Unlock()
c.Assert(assertstate.RestoreValidationSetsTracking(s.st), testutil.ErrorIs, state.ErrNoState)
}
func (s *validationSetTrackingSuite) TestRestoreValidationSetsTracking(c *C) {
s.st.Lock()
defer s.st.Unlock()
tr1 := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "bar",
Mode: assertstate.Enforce,
PinnedAt: 1,
Current: 2,
}
assertstate.UpdateValidationSet(s.st, &tr1)
c.Assert(assertstate.AddCurrentTrackingToValidationSetsHistory(s.st), IsNil)
all, err := assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Assert(all, HasLen, 1)
tr2 := assertstate.ValidationSetTracking{
AccountID: "foo",
Name: "baz",
Mode: assertstate.Enforce,
Current: 5,
}
assertstate.UpdateValidationSet(s.st, &tr2)
all, err = assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
// two validation sets are now tracked
c.Check(all, DeepEquals, map[string]*assertstate.ValidationSetTracking{
"foo/bar": &tr1,
"foo/baz": &tr2,
})
// restore
c.Assert(assertstate.RestoreValidationSetsTracking(s.st), IsNil)
// and we're back at one validation set being tracked
all, err = assertstate.ValidationSets(s.st)
c.Assert(err, IsNil)
c.Check(all, DeepEquals, map[string]*assertstate.ValidationSetTracking{
"foo/bar": &tr1,
})
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/mysnapcore/mysnapd.git
git@gitee.com:mysnapcore/mysnapd.git
mysnapcore
mysnapd
mysnapd
v0.0.1

搜索帮助