github.com/rigado/snapd@v2.42.5-go-mod+incompatible/overlord/patch/patch6_2_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 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 patch_test 21 22 import ( 23 "bytes" 24 25 . "gopkg.in/check.v1" 26 27 "github.com/snapcore/snapd/dirs" 28 "github.com/snapcore/snapd/overlord/patch" 29 "github.com/snapcore/snapd/overlord/snapstate" 30 "github.com/snapcore/snapd/overlord/state" 31 "github.com/snapcore/snapd/snap" 32 ) 33 34 type patch62Suite struct{} 35 36 var _ = Suite(&patch62Suite{}) 37 38 // State with snapd snap marked as 'app' (to be converted to 'snapd' type) and a regular 'other' snap, 39 // plus three tasks - two of them need to have their SnapSetup migrated to 'snapd' type. 40 var statePatch6_2JSON = []byte(` 41 { 42 "data": { 43 "patch-level": 6, 44 "snaps": { 45 "snapd": { 46 "type": "app", 47 "sequence": [ 48 { 49 "name": "snapd", 50 "snap-id": "snapd-snap-id", 51 "revision": "2" 52 } 53 ], 54 "active": true, 55 "current": "2", 56 "channel": "stable" 57 }, 58 "other": { 59 "type": "app", 60 "sequence": [ 61 { 62 "name": "snapd", 63 "snap-id": "foo", 64 "revision": "2" 65 } 66 ], 67 "active": true, 68 "current": "2", 69 "channel": "stable" 70 } 71 } 72 }, 73 "changes": { 74 "6": { 75 "id": "6", 76 "kind": "auto-refresh", 77 "summary": "...", 78 "status": 0, 79 "clean": true, 80 "data": { 81 "api-data": { 82 "snap-names": ["snapd"] 83 }, 84 "snap-names": ["snapd"] 85 }, 86 "task-ids": ["1", "8"] 87 }, 88 "9": { 89 "id": "9", 90 "kind": "auto-refresh", 91 "summary": "...", 92 "status": 4, 93 "clean": true, 94 "data": { 95 "api-data": { 96 "snap-names": ["snapd"] 97 }, 98 "snap-names": ["snapd"] 99 }, 100 "task-ids": ["10"] 101 } 102 }, 103 "tasks": { 104 "1": { 105 "id": "1", 106 "kind": "download-snap", 107 "summary": "...", 108 "status": 2, 109 "clean": true, 110 "data": { 111 "snap-setup": { 112 "channel": "stable", 113 "type": "app", 114 "is-auto-refresh": true, 115 "snap-path": "/path", 116 "download-info": { 117 "download-url": "foo", 118 "size": 1234, 119 "sha3-384": "123456", 120 "deltas": [ 121 { 122 "from-revision": 10934, 123 "to-revision": 10972, 124 "format": "xdelta3", 125 "download-url": "foo", 126 "size": 16431136, 127 "sha3-384": "1" 128 } 129 ] 130 }, 131 "side-info": { 132 "name": "snapd", 133 "snap-id": "snapd-snap-id", 134 "revision": "1", 135 "channel": "stable", 136 "title": "snapd" 137 }, 138 "media": [ 139 { 140 "type": "icon", 141 "url": "a" 142 }, 143 { 144 "type": "screenshot", 145 "url": "2" 146 }, 147 { 148 "type": "screenshot", 149 "url": "3" 150 }, 151 { 152 "type": "screenshot", 153 "url": "4" 154 }, 155 { 156 "type": "video", 157 "url": "5" 158 } 159 ] 160 } 161 }, 162 "change": "6" 163 }, 164 "8": { 165 "id": "8", 166 "kind": "other", 167 "summary": "", 168 "status": 4, 169 "data": { 170 "snap-setup": { 171 "channel": "stable", 172 "type": "app", 173 "snap-path": "/path", 174 "side-info": { 175 "name": "snapd", 176 "snap-id": "snapd-snap-id", 177 "revision": "1", 178 "channel": "stable", 179 "title": "snapd" 180 } 181 } 182 }, 183 "change": "6" 184 }, 185 "10": { 186 "id": "10", 187 "kind": "other", 188 "summary": "", 189 "status": 4, 190 "data": { 191 "snap-setup": { 192 "channel": "stable", 193 "type": "app", 194 "snap-path": "/path", 195 "side-info": { 196 "name": "snapd", 197 "snap-id": "snapd-snap-id", 198 "revision": "1", 199 "channel": "stable", 200 "title": "snapd" 201 } 202 } 203 }, 204 "change": "9" 205 } 206 } 207 } 208 } 209 }`) 210 211 // State with 'snapd' snap with proper snap type, and an extra 'other' snap 212 // with snapd-snap-id but improper 'app' type. 213 var statePatch6_2JSONWithSnapd = []byte(` 214 { 215 "data": { 216 "patch-level": 6, 217 "snaps": { 218 "snapd": { 219 "type": "snapd", 220 "sequence": [ 221 { 222 "name": "snapd", 223 "snap-id": "snapd-snap-id", 224 "revision": "2" 225 } 226 ], 227 "active": true, 228 "current": "2", 229 "channel": "stable" 230 }, 231 "other": { 232 "type": "app", 233 "sequence": [ 234 { 235 "name": "other", 236 "snap-id": "snapd-snap-id", 237 "revision": "1" 238 } 239 ], 240 "active": true, 241 "current": "1", 242 "channel": "stable" 243 } 244 } 245 }, 246 "changes": {} 247 }, 248 "tasks": {} 249 } 250 }`) 251 252 // State with two snaps with snapd-snap-id and improper snap types 253 var statePatch6_2JSONWithSnapd2 = []byte(` 254 { 255 "data": { 256 "patch-level": 6, 257 "snaps": { 258 "snapd": { 259 "type": "app", 260 "sequence": [ 261 { 262 "name": "snapd", 263 "snap-id": "snapd-snap-id", 264 "revision": "2" 265 } 266 ], 267 "active": true, 268 "current": "2", 269 "channel": "stable" 270 }, 271 "other": { 272 "type": "app", 273 "sequence": [ 274 { 275 "name": "other", 276 "snap-id": "snapd-snap-id", 277 "revision": "1" 278 } 279 ], 280 "active": true, 281 "current": "1", 282 "channel": "stable" 283 } 284 } 285 }, 286 "changes": {} 287 }, 288 "tasks": {} 289 } 290 }`) 291 292 func (s *patch62Suite) SetUpTest(c *C) { 293 dirs.SetRootDir(c.MkDir()) 294 snap.MockSanitizePlugsSlots(func(*snap.Info) {}) 295 } 296 297 func (s *patch62Suite) TestPatch62(c *C) { 298 restore1 := patch.MockLevel(6, 2) 299 defer restore1() 300 301 restore2 := snap.MockSnapdSnapID("snapd-snap-id") 302 defer restore2() 303 304 r := bytes.NewReader(statePatch6_2JSON) 305 st, err := state.ReadState(nil, r) 306 c.Assert(err, IsNil) 307 308 c.Assert(patch.Apply(st), IsNil) 309 st.Lock() 310 defer st.Unlock() 311 312 // our mocks are correct 313 c.Assert(st.Changes(), HasLen, 2) 314 c.Assert(st.Tasks(), HasLen, 3) 315 316 var snapst snapstate.SnapState 317 c.Assert(snapstate.Get(st, "snapd", &snapst), IsNil) 318 c.Check(snapst.SnapType, Equals, "snapd") 319 320 // sanity check - "other" is untouched 321 c.Assert(snapstate.Get(st, "other", &snapst), IsNil) 322 c.Check(snapst.SnapType, Equals, "app") 323 324 // check tasks 325 task := st.Task("1") 326 c.Assert(task, NotNil) 327 328 var snapsup snapstate.SnapSetup 329 err = task.Get("snap-setup", &snapsup) 330 c.Assert(err, IsNil) 331 c.Check(snapsup.Type, Equals, snap.TypeSnapd) 332 333 // sanity check, structures not defined explicitly via patch62* are preserved 334 c.Check(snapsup.Flags.IsAutoRefresh, Equals, true) 335 c.Assert(snapsup.Media, HasLen, 5) 336 c.Check(snapsup.Media[0].URL, Equals, "a") 337 c.Assert(snapsup.DownloadInfo, NotNil) 338 c.Check(snapsup.DownloadInfo.DownloadURL, Equals, "foo") 339 c.Check(snapsup.DownloadInfo.Deltas, HasLen, 1) 340 341 task = st.Task("8") 342 c.Assert(task, NotNil) 343 c.Assert(task.Get("snap-setup", &snapsup), IsNil) 344 c.Check(snapsup.Type, Equals, snap.TypeSnapd) 345 346 // task 10 not updated because the change is ready 347 task = st.Task("10") 348 c.Assert(task, NotNil) 349 c.Assert(task.Get("snap-setup", &snapsup), IsNil) 350 c.Check(snapsup.Type, Equals, snap.TypeApp) 351 } 352 353 func (s *patch62Suite) TestPatch62StopsAfterFirstSnapd(c *C) { 354 restore1 := patch.MockLevel(6, 2) 355 defer restore1() 356 357 restore2 := snap.MockSnapdSnapID("snapd-snap-id") 358 defer restore2() 359 360 r := bytes.NewReader(statePatch6_2JSONWithSnapd2) 361 st, err := state.ReadState(nil, r) 362 c.Assert(err, IsNil) 363 364 c.Assert(patch.Apply(st), IsNil) 365 st.Lock() 366 defer st.Unlock() 367 368 var snapdCount int 369 for _, name := range []string{"snapd", "other"} { 370 var snapst snapstate.SnapState 371 c.Assert(snapstate.Get(st, name, &snapst), IsNil) 372 if snapst.SnapType == "snapd" { 373 snapdCount++ 374 } 375 } 376 c.Check(snapdCount, Equals, 1) 377 }