github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/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) TestOpenEnvBadEmpty(c *C) { 71 empty := filepath.Join(c.MkDir(), "empty.env") 72 73 err := ioutil.WriteFile(empty, nil, 0644) 74 c.Assert(err, IsNil) 75 76 _, err = ubootenv.Open(empty) 77 c.Assert(err, ErrorMatches, `cannot open ".*": smaller than expected header`) 78 } 79 80 func (u *uenvTestSuite) TestOpenEnvBadCRC(c *C) { 81 corrupted := filepath.Join(c.MkDir(), "corrupted.env") 82 83 buf := make([]byte, 4096) 84 err := ioutil.WriteFile(corrupted, buf, 0644) 85 c.Assert(err, IsNil) 86 87 _, err = ubootenv.Open(corrupted) 88 c.Assert(err, ErrorMatches, `cannot open ".*": bad CRC 0 != .*`) 89 } 90 91 func (u *uenvTestSuite) TestGetSimple(c *C) { 92 env, err := ubootenv.Create(u.envFile, 4096) 93 c.Assert(err, IsNil) 94 env.Set("foo", "bar") 95 c.Assert(env.Get("foo"), Equals, "bar") 96 } 97 98 func (u *uenvTestSuite) TestGetNoSuchEntry(c *C) { 99 env, err := ubootenv.Create(u.envFile, 4096) 100 c.Assert(err, IsNil) 101 c.Assert(env.Get("no-such-entry"), Equals, "") 102 } 103 104 func (u *uenvTestSuite) TestImport(c *C) { 105 env, err := ubootenv.Create(u.envFile, 4096) 106 c.Assert(err, IsNil) 107 108 r := strings.NewReader("foo=bar\n#comment\n\nbaz=baz") 109 err = env.Import(r) 110 c.Assert(err, IsNil) 111 // order is alphabetic 112 c.Assert(env.String(), Equals, "baz=baz\nfoo=bar\n") 113 } 114 115 func (u *uenvTestSuite) TestImportHasError(c *C) { 116 env, err := ubootenv.Create(u.envFile, 4096) 117 c.Assert(err, IsNil) 118 119 r := strings.NewReader("foxy") 120 err = env.Import(r) 121 c.Assert(err, ErrorMatches, "Invalid line: \"foxy\"") 122 } 123 124 func (u *uenvTestSuite) TestSetEmptyUnsets(c *C) { 125 env, err := ubootenv.Create(u.envFile, 4096) 126 c.Assert(err, IsNil) 127 128 env.Set("foo", "bar") 129 c.Assert(env.String(), Equals, "foo=bar\n") 130 env.Set("foo", "") 131 c.Assert(env.String(), Equals, "") 132 } 133 134 func (u *uenvTestSuite) makeUbootEnvFromData(c *C, mockData []byte) { 135 w := bytes.NewBuffer(nil) 136 crc := crc32.ChecksumIEEE(mockData) 137 w.Write(ubootenv.WriteUint32(crc)) 138 w.Write([]byte{0}) 139 w.Write(mockData) 140 141 f, err := os.Create(u.envFile) 142 c.Assert(err, IsNil) 143 defer f.Close() 144 _, err = f.Write(w.Bytes()) 145 c.Assert(err, IsNil) 146 } 147 148 // ensure that the data after \0\0 is discarded (except for crc) 149 func (u *uenvTestSuite) TestReadStopsAfterDoubleNull(c *C) { 150 mockData := []byte{ 151 // foo=bar 152 0x66, 0x6f, 0x6f, 0x3d, 0x62, 0x61, 0x72, 153 // eof 154 0x00, 0x00, 155 // junk after eof as written by fw_setenv sometimes 156 // =b 157 0x3d, 62, 158 // empty 159 0xff, 0xff, 160 } 161 u.makeUbootEnvFromData(c, mockData) 162 163 env, err := ubootenv.Open(u.envFile) 164 c.Assert(err, IsNil) 165 c.Assert(env.String(), Equals, "foo=bar\n") 166 } 167 168 // ensure that the malformed data is not causing us to panic. 169 func (u *uenvTestSuite) TestErrorOnMalformedData(c *C) { 170 mockData := []byte{ 171 // foo 172 0x66, 0x6f, 0x6f, 173 // eof 174 0x00, 0x00, 175 } 176 u.makeUbootEnvFromData(c, mockData) 177 178 env, err := ubootenv.Open(u.envFile) 179 c.Assert(err, ErrorMatches, `cannot parse line "foo" as key=value pair`) 180 c.Assert(env, IsNil) 181 } 182 183 // ensure that the malformed data is not causing us to panic. 184 func (u *uenvTestSuite) TestOpenBestEffort(c *C) { 185 testCases := map[string][]byte{"noise": { 186 // key1=value1 187 0x6b, 0x65, 0x79, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x00, 188 // foo 189 0x66, 0x6f, 0x6f, 0x00, 190 // key2=value2 191 0x6b, 0x65, 0x79, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x00, 192 // eof 193 0x00, 0x00, 194 }, "no-eof": { 195 // key1=value1 196 0x6b, 0x65, 0x79, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x00, 197 // key2=value2 198 0x6b, 0x65, 0x79, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x00, 199 // NO EOF! 200 }, "noise-eof": { 201 // key1=value1 202 0x6b, 0x65, 0x79, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x00, 203 // key2=value2 204 0x6b, 0x65, 0x79, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x00, 205 // foo 206 0x66, 0x6f, 0x6f, 0x00, 207 }} 208 for testName, mockData := range testCases { 209 u.makeUbootEnvFromData(c, mockData) 210 211 env, err := ubootenv.OpenWithFlags(u.envFile, ubootenv.OpenBestEffort) 212 c.Assert(err, IsNil, Commentf(testName)) 213 c.Check(env.String(), Equals, "key1=value1\nkey2=value2\n", Commentf(testName)) 214 } 215 } 216 217 func (u *uenvTestSuite) TestErrorOnMissingKeyInKeyValuePair(c *C) { 218 mockData := []byte{ 219 // =foo 220 0x3d, 0x66, 0x6f, 0x6f, 221 // eof 222 0x00, 0x00, 223 } 224 u.makeUbootEnvFromData(c, mockData) 225 226 env, err := ubootenv.Open(u.envFile) 227 c.Assert(err, ErrorMatches, `cannot parse line "=foo" as key=value pair`) 228 c.Assert(env, IsNil) 229 } 230 231 func (u *uenvTestSuite) TestReadEmptyFile(c *C) { 232 mockData := []byte{ 233 // eof 234 0x00, 0x00, 235 // empty 236 0xff, 0xff, 237 } 238 u.makeUbootEnvFromData(c, mockData) 239 240 env, err := ubootenv.Open(u.envFile) 241 c.Assert(err, IsNil) 242 c.Assert(env.String(), Equals, "") 243 } 244 245 func (u *uenvTestSuite) TestWritesEmptyFileWithDoubleNewline(c *C) { 246 env, err := ubootenv.Create(u.envFile, 12) 247 c.Assert(err, IsNil) 248 err = env.Save() 249 c.Assert(err, IsNil) 250 251 r, err := os.Open(u.envFile) 252 c.Assert(err, IsNil) 253 defer r.Close() 254 content, err := ioutil.ReadAll(r) 255 c.Assert(err, IsNil) 256 c.Assert(content, DeepEquals, []byte{ 257 // crc 258 0x11, 0x38, 0xb3, 0x89, 259 // redundant 260 0x0, 261 // eof 262 0x0, 0x0, 263 // footer 264 0xff, 0xff, 0xff, 0xff, 0xff, 265 }) 266 267 env, err = ubootenv.Open(u.envFile) 268 c.Assert(err, IsNil) 269 c.Assert(env.String(), Equals, "") 270 } 271 272 func (u *uenvTestSuite) TestWritesContentCorrectly(c *C) { 273 totalSize := 16 274 275 env, err := ubootenv.Create(u.envFile, totalSize) 276 c.Assert(err, IsNil) 277 env.Set("a", "b") 278 env.Set("c", "d") 279 err = env.Save() 280 c.Assert(err, IsNil) 281 282 r, err := os.Open(u.envFile) 283 c.Assert(err, IsNil) 284 defer r.Close() 285 content, err := ioutil.ReadAll(r) 286 c.Assert(err, IsNil) 287 c.Assert(content, DeepEquals, []byte{ 288 // crc 289 0xc7, 0xd9, 0x6b, 0xc5, 290 // redundant 291 0x0, 292 // a=b 293 0x61, 0x3d, 0x62, 294 // eol 295 0x0, 296 // c=d 297 0x63, 0x3d, 0x64, 298 // eof 299 0x0, 0x0, 300 // footer 301 0xff, 0xff, 302 }) 303 304 env, err = ubootenv.Open(u.envFile) 305 c.Assert(err, IsNil) 306 c.Assert(env.String(), Equals, "a=b\nc=d\n") 307 c.Assert(env.Size(), Equals, totalSize) 308 }