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 }