github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/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  }