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  }