github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/boot/boottest/device.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-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 boottest 21 22 import ( 23 "strings" 24 25 "github.com/snapcore/snapd/asserts" 26 "github.com/snapcore/snapd/boot" 27 ) 28 29 type mockDevice struct { 30 bootSnap string 31 mode string 32 uc20 bool 33 34 model *asserts.Model 35 } 36 37 // MockDevice implements boot.Device. It wraps a string like 38 // <boot-snap-name>[@<mode>], no <boot-snap-name> means classic, empty 39 // <mode> defaults to "run" for UC16/18. If mode is set HasModeenv 40 // returns true for UC20 and an empty boot snap name panics. 41 // It returns <boot-snap-name> for both Base and Kernel, for more 42 // control mock a DeviceContext. 43 func MockDevice(s string) boot.Device { 44 bootsnap, mode, uc20 := snapAndMode(s) 45 if uc20 && bootsnap == "" { 46 panic("MockDevice with no snap name and @mode is unsupported") 47 } 48 return &mockDevice{ 49 bootSnap: bootsnap, 50 mode: mode, 51 uc20: uc20, 52 } 53 } 54 55 // MockUC20Device implements boot.Device and returns true for HasModeenv. 56 // Arguments are mode (empty means "run"), and model. 57 // If model is nil a default model is used (same as MakeMockUC20Model). 58 func MockUC20Device(mode string, model *asserts.Model) boot.Device { 59 if mode == "" { 60 mode = "run" 61 } 62 if model == nil { 63 model = MakeMockUC20Model() 64 } 65 return &mockDevice{ 66 bootSnap: model.Kernel(), 67 mode: mode, 68 uc20: true, 69 model: model, 70 } 71 } 72 73 func snapAndMode(str string) (snap, mode string, uc20 bool) { 74 parts := strings.SplitN(string(str), "@", 2) 75 if len(parts) == 1 || parts[1] == "" { 76 return parts[0], "run", false 77 } 78 return parts[0], parts[1], true 79 } 80 81 func (d *mockDevice) Kernel() string { return d.bootSnap } 82 func (d *mockDevice) Classic() bool { return d.bootSnap == "" } 83 func (d *mockDevice) RunMode() bool { return d.mode == "run" } 84 func (d *mockDevice) HasModeenv() bool { return d.uc20 } 85 func (d *mockDevice) Base() string { 86 if d.model != nil { 87 return d.model.Base() 88 } 89 return d.bootSnap 90 } 91 func (d *mockDevice) Model() *asserts.Model { 92 if d.model == nil { 93 panic("Device.Model called but MockUC20Device not used") 94 } 95 return d.model 96 }