github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/overlord/hookstate/context_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 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 hookstate 21 22 import ( 23 "encoding/json" 24 25 . "gopkg.in/check.v1" 26 27 "github.com/snapcore/snapd/overlord/state" 28 "github.com/snapcore/snapd/snap" 29 ) 30 31 type contextSuite struct { 32 context *Context 33 task *state.Task 34 state *state.State 35 setup *HookSetup 36 } 37 38 var _ = Suite(&contextSuite{}) 39 40 func (s *contextSuite) SetUpTest(c *C) { 41 s.state = state.New(nil) 42 s.state.Lock() 43 defer s.state.Unlock() 44 45 s.task = s.state.NewTask("test-task", "my test task") 46 s.setup = &HookSetup{Snap: "test-snap", Revision: snap.R(1), Hook: "test-hook"} 47 var err error 48 s.context, err = NewContext(s.task, s.task.State(), s.setup, nil, "") 49 c.Check(err, IsNil) 50 } 51 52 func (s *contextSuite) TestHookSetup(c *C) { 53 c.Check(s.context.HookName(), Equals, "test-hook") 54 c.Check(s.context.InstanceName(), Equals, "test-snap") 55 } 56 57 func (s *contextSuite) TestSetAndGet(c *C) { 58 s.context.Lock() 59 defer s.context.Unlock() 60 61 var output string 62 c.Check(s.context.Get("foo", &output), NotNil) 63 64 s.context.Set("foo", "bar") 65 c.Check(s.context.Get("foo", &output), IsNil, Commentf("Expected context to contain 'foo'")) 66 c.Check(output, Equals, "bar") 67 68 // Test another non-existing key, but after the context data was created. 69 c.Check(s.context.Get("baz", &output), NotNil) 70 } 71 72 func (s *contextSuite) TestSetAndGetNumber(c *C) { 73 s.context.Lock() 74 defer s.context.Unlock() 75 76 s.context.Set("num", 1234567890) 77 78 var output interface{} 79 c.Check(s.context.Get("num", &output), IsNil) 80 c.Assert(output, Equals, json.Number("1234567890")) 81 } 82 83 func (s *contextSuite) TestSetPersistence(c *C) { 84 s.context.Lock() 85 s.context.Set("foo", "bar") 86 s.context.Unlock() 87 88 // Verify that "foo" is still "bar" within another context of the same hook 89 // on the same task. 90 anotherContext := &Context{task: s.task, state: s.task.State(), setup: s.setup} 91 anotherContext.Lock() 92 defer anotherContext.Unlock() 93 94 var output string 95 c.Check(anotherContext.Get("foo", &output), IsNil, Commentf("Expected new context to also contain 'foo'")) 96 c.Check(output, Equals, "bar") 97 } 98 99 func (s *contextSuite) TestSetUnmarshalable(c *C) { 100 s.context.Lock() 101 defer s.context.Unlock() 102 103 defer func() { 104 c.Check(recover(), Matches, ".*cannot marshal context value.*", Commentf("Expected panic when attempting install")) 105 }() 106 107 s.context.Set("foo", func() {}) 108 } 109 110 func (s *contextSuite) TestGetIsolatedFromTask(c *C) { 111 // Set data in the task itself 112 s.task.State().Lock() 113 s.task.Set("foo", "bar") 114 s.task.State().Unlock() 115 116 s.context.Lock() 117 defer s.context.Unlock() 118 119 // Verify that "foo" is not set when asking for data from the hook context 120 var output string 121 c.Check(s.context.Get("foo", &output), NotNil, Commentf("Expected context data to be isolated from task")) 122 } 123 124 func (s *contextSuite) TestCache(c *C) { 125 s.context.Lock() 126 defer s.context.Unlock() 127 128 c.Check(s.context.Cached("foo"), IsNil) 129 130 s.context.Cache("foo", "bar") 131 c.Check(s.context.Cached("foo"), Equals, "bar") 132 133 // Test another non-existing key, but after the context cache was created. 134 c.Check(s.context.Cached("baz"), IsNil) 135 } 136 137 func (s *contextSuite) TestDone(c *C) { 138 s.context.Lock() 139 defer s.context.Unlock() 140 141 called := false 142 s.context.OnDone(func() error { 143 called = true 144 return nil 145 }) 146 147 s.context.Done() 148 c.Check(called, Equals, true, Commentf("Expected finalizer to be called")) 149 } 150 151 func (s *contextSuite) TestEphemeralContextGetSet(c *C) { 152 context, err := NewContext(nil, s.state, &HookSetup{Snap: "test-snap"}, nil, "") 153 c.Assert(err, IsNil) 154 context.Lock() 155 defer context.Unlock() 156 157 var output string 158 c.Check(context.Get("foo", &output), NotNil) 159 160 context.Set("foo", "bar") 161 c.Check(context.Get("foo", &output), IsNil, Commentf("Expected context to contain 'foo'")) 162 c.Check(output, Equals, "bar") 163 164 // Test another non-existing key, but after the context data was created. 165 c.Check(context.Get("baz", &output), NotNil) 166 } 167 168 func (s *contextSuite) TestChangeID(c *C) { 169 context, err := NewContext(nil, s.state, &HookSetup{Snap: "test-snap"}, nil, "") 170 c.Assert(err, IsNil) 171 c.Check(context.ChangeID(), Equals, "") 172 173 s.state.Lock() 174 defer s.state.Unlock() 175 176 task := s.state.NewTask("foo", "") 177 context, err = NewContext(task, s.state, &HookSetup{Snap: "test-snap"}, nil, "") 178 c.Assert(err, IsNil) 179 c.Check(context.ChangeID(), Equals, "") 180 181 chg := s.state.NewChange("bar", "") 182 chg.AddTask(task) 183 context, err = NewContext(task, s.state, &HookSetup{Snap: "test-snap"}, nil, "") 184 c.Assert(err, IsNil) 185 c.Check(context.ChangeID(), Equals, chg.ID()) 186 }