github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/snap/cmd_debug_state_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 main_test 21 22 import ( 23 "io/ioutil" 24 "path/filepath" 25 26 . "gopkg.in/check.v1" 27 28 main "github.com/snapcore/snapd/cmd/snap" 29 ) 30 31 var stateJSON = []byte(` 32 { 33 "last-task-id": 31, 34 "last-change-id": 2, 35 36 "data": { 37 "snaps": {}, 38 "seeded": true 39 }, 40 "changes": { 41 "1": { 42 "id": "1", 43 "kind": "install-snap", 44 "summary": "install a snap", 45 "status": 0, 46 "data": {"snap-names": ["a"]}, 47 "task-ids": ["11","12"] 48 }, 49 "2": { 50 "id": "2", 51 "kind": "revert-snap", 52 "summary": "revert c snap", 53 "status": 0, 54 "data": {"snap-names": ["c"]}, 55 "task-ids": ["21","31"] 56 } 57 }, 58 "tasks": { 59 "11": { 60 "id": "11", 61 "change": "1", 62 "kind": "download-snap", 63 "summary": "Download snap a from channel edge", 64 "status": 4, 65 "data": {"snap-setup": { 66 "channel": "edge", 67 "flags": 1 68 }}, 69 "halt-tasks": ["12"] 70 }, 71 "12": {"id": "12", "change": "1", "kind": "some-other-task"}, 72 "21": { 73 "id": "21", 74 "change": "2", 75 "kind": "download-snap", 76 "summary": "Download snap b from channel beta", 77 "status": 4, 78 "data": {"snap-setup": { 79 "channel": "beta", 80 "flags": 2 81 }}, 82 "halt-tasks": ["12"] 83 }, 84 "31": { 85 "id": "31", 86 "change": "2", 87 "kind": "prepare-snap", 88 "summary": "Prepare snap c", 89 "status": 4, 90 "data": {"snap-setup": { 91 "channel": "stable", 92 "flags": 1073741828 93 }}, 94 "halt-tasks": ["12"], 95 "log": ["logline1", "logline2"] 96 } 97 } 98 } 99 `) 100 101 var stateCyclesJSON = []byte(` 102 { 103 "last-task-id": 14, 104 "last-change-id": 2, 105 106 "data": { 107 "snaps": {}, 108 "seeded": true 109 }, 110 "changes": { 111 "1": { 112 "id": "1", 113 "kind": "install-snap", 114 "summary": "install a snap", 115 "status": 0, 116 "task-ids": ["11","12","13"] 117 } 118 }, 119 "tasks": { 120 "11": { 121 "id": "11", 122 "change": "1", 123 "kind": "foo", 124 "summary": "Foo task", 125 "status": 4, 126 "halt-tasks": ["13"] 127 }, 128 "12": { 129 "id": "12", 130 "change": "1", 131 "kind": "bar", 132 "summary": "Bar task", 133 "halt-tasks": ["13"] 134 }, 135 "13": { 136 "id": "13", 137 "change": "1", 138 "kind": "bar", 139 "summary": "Bar task", 140 "halt-tasks": ["11","12"] 141 } 142 } 143 } 144 `) 145 146 func (s *SnapSuite) TestDebugChanges(c *C) { 147 dir := c.MkDir() 148 stateFile := filepath.Join(dir, "test-state.json") 149 c.Assert(ioutil.WriteFile(stateFile, stateJSON, 0644), IsNil) 150 151 rest, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--abs-time", "--changes", stateFile}) 152 c.Assert(err, IsNil) 153 c.Assert(rest, DeepEquals, []string{}) 154 c.Check(s.Stdout(), Matches, 155 "ID Status Spawn Ready Label Summary\n"+ 156 "1 Do 0001-01-01T00:00:00Z 0001-01-01T00:00:00Z install-snap install a snap\n"+ 157 "2 Done 0001-01-01T00:00:00Z 0001-01-01T00:00:00Z revert-snap revert c snap\n") 158 c.Check(s.Stderr(), Equals, "") 159 } 160 161 func (s *SnapSuite) TestDebugChangesMissingState(c *C) { 162 _, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--changes", "/missing-state.json"}) 163 c.Check(err, ErrorMatches, "cannot read the state file: open /missing-state.json: no such file or directory") 164 } 165 166 func (s *SnapSuite) TestDebugTask(c *C) { 167 dir := c.MkDir() 168 stateFile := filepath.Join(dir, "test-state.json") 169 c.Assert(ioutil.WriteFile(stateFile, stateJSON, 0644), IsNil) 170 171 rest, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--task=31", stateFile}) 172 c.Assert(err, IsNil) 173 c.Assert(rest, DeepEquals, []string{}) 174 c.Check(s.Stdout(), Equals, "id: 31\n"+ 175 "kind: prepare-snap\n"+ 176 "summary: Prepare snap c\n"+ 177 "status: Done\n"+ 178 "log: |\n"+ 179 " logline1\n"+ 180 " logline2\n"+ 181 "\n"+ 182 "halt-tasks:\n"+ 183 " - some-other-task (12)\n") 184 c.Check(s.Stderr(), Equals, "") 185 } 186 187 func (s *SnapSuite) TestDebugTaskEmptyLists(c *C) { 188 dir := c.MkDir() 189 stateFile := filepath.Join(dir, "test-state.json") 190 c.Assert(ioutil.WriteFile(stateFile, stateJSON, 0644), IsNil) 191 192 rest, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--task=12", stateFile}) 193 c.Assert(err, IsNil) 194 c.Assert(rest, DeepEquals, []string{}) 195 c.Check(s.Stdout(), Equals, "id: 12\n"+ 196 "kind: some-other-task\n"+ 197 "summary: \n"+ 198 "status: Do\n"+ 199 "halt-tasks: []\n") 200 c.Check(s.Stderr(), Equals, "") 201 } 202 203 func (s *SnapSuite) TestDebugTaskMissingState(c *C) { 204 _, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--task=1", "/missing-state.json"}) 205 c.Check(err, ErrorMatches, "cannot read the state file: open /missing-state.json: no such file or directory") 206 } 207 208 func (s *SnapSuite) TestDebugTaskNoSuchTaskError(c *C) { 209 dir := c.MkDir() 210 stateFile := filepath.Join(dir, "test-state.json") 211 c.Assert(ioutil.WriteFile(stateFile, stateJSON, 0644), IsNil) 212 213 _, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--task=99", stateFile}) 214 c.Check(err, ErrorMatches, "no such task: 99") 215 } 216 217 func (s *SnapSuite) TestDebugTaskMutuallyExclusiveCommands(c *C) { 218 dir := c.MkDir() 219 stateFile := filepath.Join(dir, "test-state.json") 220 c.Assert(ioutil.WriteFile(stateFile, stateJSON, 0644), IsNil) 221 222 _, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--task=99", "--changes", stateFile}) 223 c.Check(err, ErrorMatches, "cannot use --changes and --task= together") 224 225 _, err = main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--changes", "--change=1", stateFile}) 226 c.Check(err, ErrorMatches, "cannot use --changes and --change= together") 227 228 _, err = main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--change=1", "--task=1", stateFile}) 229 c.Check(err, ErrorMatches, "cannot use --change= and --task= together") 230 231 _, err = main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--change=1", "--is-seeded", stateFile}) 232 c.Check(err, ErrorMatches, "cannot use --change= and --is-seeded together") 233 } 234 235 func (s *SnapSuite) TestDebugTasks(c *C) { 236 dir := c.MkDir() 237 stateFile := filepath.Join(dir, "test-state.json") 238 c.Assert(ioutil.WriteFile(stateFile, stateJSON, 0644), IsNil) 239 240 rest, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--abs-time", "--change=1", stateFile}) 241 c.Assert(err, IsNil) 242 c.Assert(rest, DeepEquals, []string{}) 243 c.Check(s.Stdout(), Matches, 244 "Lanes ID Status Spawn Ready Kind Summary\n"+ 245 "0 11 Done 0001-01-01T00:00:00Z 0001-01-01T00:00:00Z download-snap Download snap a from channel edge\n"+ 246 "0 12 Do 0001-01-01T00:00:00Z 0001-01-01T00:00:00Z some-other-task \n") 247 c.Check(s.Stderr(), Equals, "") 248 } 249 250 func (s *SnapSuite) TestDebugTasksWithCycles(c *C) { 251 dir := c.MkDir() 252 stateFile := filepath.Join(dir, "test-state.json") 253 c.Assert(ioutil.WriteFile(stateFile, stateCyclesJSON, 0644), IsNil) 254 255 rest, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--abs-time", "--change=1", stateFile}) 256 c.Assert(err, IsNil) 257 c.Assert(rest, DeepEquals, []string{}) 258 c.Check(s.Stdout(), Matches, 259 "Lanes ID Status Spawn Ready Kind Summary\n"+ 260 "0 13 Do 0001-01-01T00:00:00Z 0001-01-01T00:00:00Z bar Bar task\n"+ 261 "0 12 Do 0001-01-01T00:00:00Z 0001-01-01T00:00:00Z bar Bar task\n"+ 262 "0 11 Done 0001-01-01T00:00:00Z 0001-01-01T00:00:00Z foo Foo task\n") 263 c.Check(s.Stderr(), Equals, "") 264 } 265 266 func (s *SnapSuite) TestDebugTasksMissingState(c *C) { 267 _, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--change=1", "/missing-state.json"}) 268 c.Check(err, ErrorMatches, "cannot read the state file: open /missing-state.json: no such file or directory") 269 } 270 271 func (s *SnapSuite) TestDebugIsSeededHappy(c *C) { 272 dir := c.MkDir() 273 stateFile := filepath.Join(dir, "test-state.json") 274 c.Assert(ioutil.WriteFile(stateFile, stateJSON, 0644), IsNil) 275 276 rest, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--is-seeded", stateFile}) 277 c.Assert(err, IsNil) 278 c.Assert(rest, DeepEquals, []string{}) 279 c.Check(s.Stdout(), Matches, "true\n") 280 c.Check(s.Stderr(), Equals, "") 281 } 282 283 func (s *SnapSuite) TestDebugIsSeededNo(c *C) { 284 dir := c.MkDir() 285 stateFile := filepath.Join(dir, "test-state.json") 286 c.Assert(ioutil.WriteFile(stateFile, []byte("{}"), 0644), IsNil) 287 288 rest, err := main.Parser(main.Client()).ParseArgs([]string{"debug", "state", "--is-seeded", stateFile}) 289 c.Assert(err, IsNil) 290 c.Assert(rest, DeepEquals, []string{}) 291 c.Check(s.Stdout(), Matches, "false\n") 292 c.Check(s.Stderr(), Equals, "") 293 }