github.com/rigado/snapd@v2.42.5-go-mod+incompatible/bootloader/ubootenv/env_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016-2017 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 ubootenv_test
    21  
    22  import (
    23  	"bytes"
    24  	"hash/crc32"
    25  	"io/ioutil"
    26  	"os"
    27  	"path/filepath"
    28  	"strings"
    29  	"testing"
    30  
    31  	. "gopkg.in/check.v1"
    32  
    33  	"github.com/snapcore/snapd/bootloader/ubootenv"
    34  )
    35  
    36  // Hook up check.v1 into the "go test" runner
    37  func Test(t *testing.T) { TestingT(t) }
    38  
    39  type uenvTestSuite struct {
    40  	envFile string
    41  }
    42  
    43  var _ = Suite(&uenvTestSuite{})
    44  
    45  func (u *uenvTestSuite) SetUpTest(c *C) {
    46  	u.envFile = filepath.Join(c.MkDir(), "uboot.env")
    47  }
    48  
    49  func (u *uenvTestSuite) TestSetNoDuplicate(c *C) {
    50  	env, err := ubootenv.Create(u.envFile, 4096)
    51  	c.Assert(err, IsNil)
    52  	env.Set("foo", "bar")
    53  	env.Set("foo", "bar")
    54  	c.Assert(env.String(), Equals, "foo=bar\n")
    55  }
    56  
    57  func (u *uenvTestSuite) TestOpenEnv(c *C) {
    58  	env, err := ubootenv.Create(u.envFile, 4096)
    59  	c.Assert(err, IsNil)
    60  	env.Set("foo", "bar")
    61  	c.Assert(env.String(), Equals, "foo=bar\n")
    62  	err = env.Save()
    63  	c.Assert(err, IsNil)
    64  
    65  	env2, err := ubootenv.Open(u.envFile)
    66  	c.Assert(err, IsNil)
    67  	c.Assert(env2.String(), Equals, "foo=bar\n")
    68  }
    69  
    70  func (u *uenvTestSuite) TestOpenEnvBadCRC(c *C) {
    71  	corrupted := filepath.Join(c.MkDir(), "corrupted.env")
    72  
    73  	buf := make([]byte, 4096)
    74  	err := ioutil.WriteFile(corrupted, buf, 0644)
    75  	c.Assert(err, IsNil)
    76  
    77  	_, err = ubootenv.Open(corrupted)
    78  	c.Assert(err, ErrorMatches, `cannot open ".*": bad CRC 0 != .*`)
    79  }
    80  
    81  func (u *uenvTestSuite) TestGetSimple(c *C) {
    82  	env, err := ubootenv.Create(u.envFile, 4096)
    83  	c.Assert(err, IsNil)
    84  	env.Set("foo", "bar")
    85  	c.Assert(env.Get("foo"), Equals, "bar")
    86  }
    87  
    88  func (u *uenvTestSuite) TestGetNoSuchEntry(c *C) {
    89  	env, err := ubootenv.Create(u.envFile, 4096)
    90  	c.Assert(err, IsNil)
    91  	c.Assert(env.Get("no-such-entry"), Equals, "")
    92  }
    93  
    94  func (u *uenvTestSuite) TestImport(c *C) {
    95  	env, err := ubootenv.Create(u.envFile, 4096)
    96  	c.Assert(err, IsNil)
    97  
    98  	r := strings.NewReader("foo=bar\n#comment\n\nbaz=baz")
    99  	err = env.Import(r)
   100  	c.Assert(err, IsNil)
   101  	// order is alphabetic
   102  	c.Assert(env.String(), Equals, "baz=baz\nfoo=bar\n")
   103  }
   104  
   105  func (u *uenvTestSuite) TestImportHasError(c *C) {
   106  	env, err := ubootenv.Create(u.envFile, 4096)
   107  	c.Assert(err, IsNil)
   108  
   109  	r := strings.NewReader("foxy")
   110  	err = env.Import(r)
   111  	c.Assert(err, ErrorMatches, "Invalid line: \"foxy\"")
   112  }
   113  
   114  func (u *uenvTestSuite) TestSetEmptyUnsets(c *C) {
   115  	env, err := ubootenv.Create(u.envFile, 4096)
   116  	c.Assert(err, IsNil)
   117  
   118  	env.Set("foo", "bar")
   119  	c.Assert(env.String(), Equals, "foo=bar\n")
   120  	env.Set("foo", "")
   121  	c.Assert(env.String(), Equals, "")
   122  }
   123  
   124  func (u *uenvTestSuite) makeUbootEnvFromData(c *C, mockData []byte) {
   125  	w := bytes.NewBuffer(nil)
   126  	crc := crc32.ChecksumIEEE(mockData)
   127  	w.Write(ubootenv.WriteUint32(crc))
   128  	w.Write([]byte{0})
   129  	w.Write(mockData)
   130  
   131  	f, err := os.Create(u.envFile)
   132  	c.Assert(err, IsNil)
   133  	defer f.Close()
   134  	_, err = f.Write(w.Bytes())
   135  	c.Assert(err, IsNil)
   136  }
   137  
   138  // ensure that the data after \0\0 is discarded (except for crc)
   139  func (u *uenvTestSuite) TestReadStopsAfterDoubleNull(c *C) {
   140  	mockData := []byte{
   141  		// foo=bar
   142  		0x66, 0x6f, 0x6f, 0x3d, 0x62, 0x61, 0x72,
   143  		// eof
   144  		0x00, 0x00,
   145  		// junk after eof as written by fw_setenv sometimes
   146  		// =b
   147  		0x3d, 62,
   148  		// empty
   149  		0xff, 0xff,
   150  	}
   151  	u.makeUbootEnvFromData(c, mockData)
   152  
   153  	env, err := ubootenv.Open(u.envFile)
   154  	c.Assert(err, IsNil)
   155  	c.Assert(env.String(), Equals, "foo=bar\n")
   156  }
   157  
   158  // ensure that the malformed data is not causing us to panic.
   159  func (u *uenvTestSuite) TestErrorOnMalformedData(c *C) {
   160  	mockData := []byte{
   161  		// foo
   162  		0x66, 0x6f, 0x6f,
   163  		// eof
   164  		0x00, 0x00,
   165  	}
   166  	u.makeUbootEnvFromData(c, mockData)
   167  
   168  	env, err := ubootenv.Open(u.envFile)
   169  	c.Assert(err, ErrorMatches, `cannot parse line "foo" as key=value pair`)
   170  	c.Assert(env, IsNil)
   171  }
   172  
   173  // ensure that the malformed data is not causing us to panic.
   174  func (u *uenvTestSuite) TestOpenBestEffort(c *C) {
   175  	testCases := map[string][]byte{"noise": {
   176  		// key1=value1
   177  		0x6b, 0x65, 0x79, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x00,
   178  		// foo
   179  		0x66, 0x6f, 0x6f, 0x00,
   180  		// key2=value2
   181  		0x6b, 0x65, 0x79, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x00,
   182  		// eof
   183  		0x00, 0x00,
   184  	}, "no-eof": {
   185  		// key1=value1
   186  		0x6b, 0x65, 0x79, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x00,
   187  		// key2=value2
   188  		0x6b, 0x65, 0x79, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x00,
   189  		// NO EOF!
   190  	}, "noise-eof": {
   191  		// key1=value1
   192  		0x6b, 0x65, 0x79, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x00,
   193  		// key2=value2
   194  		0x6b, 0x65, 0x79, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x00,
   195  		// foo
   196  		0x66, 0x6f, 0x6f, 0x00,
   197  	}}
   198  	for testName, mockData := range testCases {
   199  		u.makeUbootEnvFromData(c, mockData)
   200  
   201  		env, err := ubootenv.OpenWithFlags(u.envFile, ubootenv.OpenBestEffort)
   202  		c.Assert(err, IsNil, Commentf(testName))
   203  		c.Check(env.String(), Equals, "key1=value1\nkey2=value2\n", Commentf(testName))
   204  	}
   205  }
   206  
   207  func (u *uenvTestSuite) TestErrorOnMissingKeyInKeyValuePair(c *C) {
   208  	mockData := []byte{
   209  		// =foo
   210  		0x3d, 0x66, 0x6f, 0x6f,
   211  		// eof
   212  		0x00, 0x00,
   213  	}
   214  	u.makeUbootEnvFromData(c, mockData)
   215  
   216  	env, err := ubootenv.Open(u.envFile)
   217  	c.Assert(err, ErrorMatches, `cannot parse line "=foo" as key=value pair`)
   218  	c.Assert(env, IsNil)
   219  }
   220  
   221  func (u *uenvTestSuite) TestReadEmptyFile(c *C) {
   222  	mockData := []byte{
   223  		// eof
   224  		0x00, 0x00,
   225  		// empty
   226  		0xff, 0xff,
   227  	}
   228  	u.makeUbootEnvFromData(c, mockData)
   229  
   230  	env, err := ubootenv.Open(u.envFile)
   231  	c.Assert(err, IsNil)
   232  	c.Assert(env.String(), Equals, "")
   233  }
   234  
   235  func (u *uenvTestSuite) TestWritesEmptyFileWithDoubleNewline(c *C) {
   236  	env, err := ubootenv.Create(u.envFile, 12)
   237  	c.Assert(err, IsNil)
   238  	err = env.Save()
   239  	c.Assert(err, IsNil)
   240  
   241  	r, err := os.Open(u.envFile)
   242  	c.Assert(err, IsNil)
   243  	defer r.Close()
   244  	content, err := ioutil.ReadAll(r)
   245  	c.Assert(err, IsNil)
   246  	c.Assert(content, DeepEquals, []byte{
   247  		// crc
   248  		0x11, 0x38, 0xb3, 0x89,
   249  		// redundant
   250  		0x0,
   251  		// eof
   252  		0x0, 0x0,
   253  		// footer
   254  		0xff, 0xff, 0xff, 0xff, 0xff,
   255  	})
   256  
   257  	env, err = ubootenv.Open(u.envFile)
   258  	c.Assert(err, IsNil)
   259  	c.Assert(env.String(), Equals, "")
   260  }
   261  
   262  func (u *uenvTestSuite) TestWritesContentCorrectly(c *C) {
   263  	totalSize := 16
   264  
   265  	env, err := ubootenv.Create(u.envFile, totalSize)
   266  	c.Assert(err, IsNil)
   267  	env.Set("a", "b")
   268  	env.Set("c", "d")
   269  	err = env.Save()
   270  	c.Assert(err, IsNil)
   271  
   272  	r, err := os.Open(u.envFile)
   273  	c.Assert(err, IsNil)
   274  	defer r.Close()
   275  	content, err := ioutil.ReadAll(r)
   276  	c.Assert(err, IsNil)
   277  	c.Assert(content, DeepEquals, []byte{
   278  		// crc
   279  		0xc7, 0xd9, 0x6b, 0xc5,
   280  		// redundant
   281  		0x0,
   282  		// a=b
   283  		0x61, 0x3d, 0x62,
   284  		// eol
   285  		0x0,
   286  		// c=d
   287  		0x63, 0x3d, 0x64,
   288  		// eof
   289  		0x0, 0x0,
   290  		// footer
   291  		0xff, 0xff,
   292  	})
   293  
   294  	env, err = ubootenv.Open(u.envFile)
   295  	c.Assert(err, IsNil)
   296  	c.Assert(env.String(), Equals, "a=b\nc=d\n")
   297  	c.Assert(env.Size(), Equals, totalSize)
   298  }