gitee.com/mysnapcore/mysnapd@v0.1.0/cmd/snap/cmd_debug_migrate_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2022 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 "fmt" 24 "net/http" 25 26 snap "gitee.com/mysnapcore/mysnapd/cmd/snap" 27 "gopkg.in/check.v1" 28 . "gopkg.in/check.v1" 29 ) 30 31 type MigrateHomeSuite struct { 32 BaseSnapSuite 33 } 34 35 var _ = check.Suite(&MigrateHomeSuite{}) 36 37 // failRequest logs an error message, fails the test and returns a proper error 38 // to the client. Use this instead of panic() or c.Fatal() because those crash 39 // the server and leave the client hanging/retrying. 40 func failRequest(msg string, w http.ResponseWriter, c *C) { 41 c.Error(msg) 42 w.WriteHeader(400) 43 fmt.Fprintf(w, `{"type": "error", "status-code": 400, "result": {"message": %q}}`, msg) 44 } 45 46 func serverWithChange(chgRsp string, c *C) func(w http.ResponseWriter, r *http.Request) { 47 var n int 48 return func(w http.ResponseWriter, r *http.Request) { 49 switch n { 50 case 0: 51 c.Check(r.Method, check.Equals, "POST") 52 c.Check(r.URL.Path, check.Equals, "/v2/debug") 53 c.Check(DecodedRequestBody(c, r), check.DeepEquals, map[string]interface{}{ 54 "action": "migrate-home", 55 "snaps": []interface{}{"foo"}, 56 }) 57 w.WriteHeader(202) 58 fmt.Fprintln(w, `{"type": "async", "status-code": 202, "result": {}, "change": "12"}`) 59 60 case 1: 61 c.Check(r.Method, check.Equals, "GET") 62 c.Check(r.URL.Path, check.Equals, "/v2/changes/12") 63 fmt.Fprintf(w, chgRsp) 64 65 default: 66 failRequest(fmt.Sprintf("server expected to get 2 requests, now on %d", n+1), w, c) 67 } 68 69 n++ 70 } 71 } 72 73 func (s *MigrateHomeSuite) TestMigrateHome(c *C) { 74 rsp := serverWithChange(`{"type": "sync", "result": {"ready": true, "status": "Done", "data": {"snap-names": ["foo"]}}}\n`, c) 75 s.RedirectClientToTestServer(rsp) 76 77 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"debug", "migrate-home", "foo"}) 78 c.Assert(err, check.IsNil) 79 c.Assert(rest, check.DeepEquals, []string{}) 80 c.Check(s.Stdout(), check.Equals, "foo's home directory was migrated to ~/Snap\n") 81 c.Check(s.Stderr(), check.Equals, "") 82 } 83 84 func (s *MigrateHomeSuite) TestMigrateHomeManySnaps(c *C) { 85 n := 0 86 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 87 switch n { 88 case 0: 89 c.Check(r.Method, check.Equals, "POST") 90 c.Check(r.URL.Path, check.Equals, "/v2/debug") 91 c.Check(DecodedRequestBody(c, r), check.DeepEquals, map[string]interface{}{ 92 "action": "migrate-home", 93 "snaps": []interface{}{"foo", "bar"}, 94 }) 95 w.WriteHeader(202) 96 fmt.Fprintln(w, `{"type": "async", "status-code": 202, "result": {}, "change": "12"}`) 97 98 case 1: 99 c.Check(r.Method, check.Equals, "GET") 100 c.Check(r.URL.Path, check.Equals, "/v2/changes/12") 101 fmt.Fprintf(w, `{"type": "sync", "result": {"ready": true, "status": "Done", "data": {"snap-names": ["foo", "bar"]}}}\n`) 102 103 default: 104 failRequest(fmt.Sprintf("server expected to get 2 requests, now on %d", n+1), w, c) 105 } 106 107 n++ 108 }) 109 110 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"debug", "migrate-home", "foo", "bar"}) 111 c.Assert(err, check.IsNil) 112 c.Assert(rest, check.DeepEquals, []string{}) 113 c.Check(s.Stdout(), check.Equals, "\"foo\", \"bar\" migrated their home directories to ~/Snap\n") 114 c.Check(s.Stderr(), check.Equals, "") 115 } 116 117 func (s *MigrateHomeSuite) TestMigrateHomeNoSnaps(c *C) { 118 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 119 failRequest("unexpected request on server", w, c) 120 }) 121 122 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"debug", "migrate-home"}) 123 c.Assert(err, check.ErrorMatches, "the required argument .* was not provided") 124 c.Check(s.Stdout(), check.Equals, "") 125 c.Check(s.Stderr(), check.Equals, "") 126 } 127 128 func (s *MigrateHomeSuite) TestMigrateHomeServerError(c *C) { 129 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 130 w.WriteHeader(500) 131 fmt.Fprintf(w, `{"type": "error", "status-code": 500, "result": {"message": "boom"}}`) 132 }) 133 134 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"debug", "migrate-home", "foo"}) 135 c.Assert(err, check.ErrorMatches, "boom") 136 c.Check(s.Stdout(), check.Equals, "") 137 c.Check(s.Stderr(), check.Equals, "") 138 } 139 140 func (s *MigrateHomeSuite) TestMigrateHomeBadChangeNoSnaps(c *C) { 141 // broken change response: missing required "snap-names" 142 srv := serverWithChange(`{"type": "sync", "result": {"ready": true, "status": "Done", "data": {"snap-names": []}}}\n`, c) 143 s.RedirectClientToTestServer(srv) 144 145 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"debug", "migrate-home", "foo"}) 146 c.Assert(err, check.ErrorMatches, `expected "migrate-home" change to have non-empty "snap-names"`) 147 c.Check(s.Stdout(), check.Equals, "") 148 c.Check(s.Stderr(), check.Equals, "") 149 } 150 151 func (s *MigrateHomeSuite) TestMigrateHomeBadChangeNoData(c *C) { 152 // broken change response: missing data 153 srv := serverWithChange(`{"type": "sync", "result": {"ready": true, "status": "Done"}}\n`, c) 154 s.RedirectClientToTestServer(srv) 155 156 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"debug", "migrate-home", "foo"}) 157 c.Assert(err, check.ErrorMatches, `cannot get "snap-names" from change`) 158 c.Check(s.Stdout(), check.Equals, "") 159 c.Check(s.Stderr(), check.Equals, "") 160 }