func (s *snapmgrTestSuite) TestAliasMatrixTotalUndoRunThrough(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "alias-snap", Revision: snap.R(11)}, }, Current: snap.R(11), Active: true, }) // alias1 is a non auto-alias // alias5 is an auto-alias // alias1lost is a non auto-alias and doesn't have an entry in the snap anymore // alias5lost is an auto-alias and doesn't have an entry in the snap any snapstate.AutoAliases = func(st *state.State, info *snap.Info) ([]string, error) { c.Check(info.Name(), Equals, "alias-snap") return []string{"alias5", "alias5lost"}, nil } cmds := map[string]string{ "alias1": "cmd1", "alias5": "cmd5", } defer s.snapmgr.Stop() for _, scenario := range statusesMatrix { scenAlias := scenario.alias if scenario.beforeStatus != "" { s.state.Set("aliases", map[string]map[string]string{ "alias-snap": { scenAlias: scenario.beforeStatus, }, }) } else { s.state.Set("aliases", nil) } chg := s.state.NewChange("scenario", "...") var err error var ts *state.TaskSet targets := []string{scenAlias} switch scenario.action { case "alias": ts, err = snapstate.Alias(s.state, "alias-snap", targets) case "unalias": ts, err = snapstate.Unalias(s.state, "alias-snap", targets) case "reset": ts, err = snapstate.ResetAliases(s.state, "alias-snap", targets) } c.Assert(err, IsNil) chg.AddAll(ts) tasks := ts.Tasks() last := tasks[len(tasks)-1] terr := s.state.NewTask("error-trigger", "provoking total undo") terr.WaitFor(last) chg.AddTask(terr) s.state.Unlock() for i := 0; i < 3; i++ { s.snapmgr.Ensure() s.snapmgr.Wait() } s.state.Lock() c.Assert(chg.Status(), Equals, state.ErrorStatus, Commentf("%#v: %v", scenario, chg.Err())) var aliases []*backend.Alias var rmAliases []*backend.Alias beAlias := &backend.Alias{scenAlias, fmt.Sprintf("alias-snap.%s", cmds[scenAlias])} switch scenario.mutation { case "-": case "add": aliases = []*backend.Alias{beAlias} case "rm": rmAliases = []*backend.Alias{beAlias} } comm := Commentf("%#v", scenario) expected := fakeOps{ { op: "update-aliases", aliases: aliases, rmAliases: rmAliases, }, { op: "matching-aliases", aliases: aliases, }, { op: "missing-aliases", aliases: rmAliases, }, { op: "update-aliases", aliases: rmAliases, rmAliases: aliases, }, } // start with an easier-to-read error if this fails: c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops(), comm) c.Assert(s.fakeBackend.ops, DeepEquals, expected, comm) var allAliases map[string]map[string]string err = s.state.Get("aliases", &allAliases) c.Assert(err, IsNil) if scenario.beforeStatus != "" { c.Check(allAliases, DeepEquals, map[string]map[string]string{ "alias-snap": {scenAlias: scenario.beforeStatus}, }, comm) } else { c.Check(allAliases, HasLen, 0, comm) } s.fakeBackend.ops = nil } }
func (s *snapmgrTestSuite) TestAliasMatrixTotalUndoRunThrough(c *C) { s.state.Lock() defer s.state.Unlock() snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ Sequence: []*snap.SideInfo{ {RealName: "alias-snap", Revision: snap.R(11)}, }, Current: snap.R(11), Active: true, }) defer s.snapmgr.Stop() for _, scenario := range statusesMatrix { if scenario.beforeStatus != "" { s.state.Set("aliases", map[string]map[string]string{ "alias-snap": { "alias1": scenario.beforeStatus, }, }) } else { s.state.Set("aliases", nil) } chg := s.state.NewChange("scenario", "...") var err error var ts *state.TaskSet switch scenario.action { case "alias": ts, err = snapstate.Alias(s.state, "alias-snap", []string{"alias1"}) case "unalias": ts, err = snapstate.Unalias(s.state, "alias-snap", []string{"alias1"}) } c.Assert(err, IsNil) chg.AddAll(ts) tasks := ts.Tasks() last := tasks[len(tasks)-1] terr := s.state.NewTask("error-trigger", "provoking total undo") terr.WaitFor(last) chg.AddTask(terr) s.state.Unlock() for i := 0; i < 3; i++ { s.snapmgr.Ensure() s.snapmgr.Wait() } s.state.Lock() c.Assert(chg.Status(), Equals, state.ErrorStatus, Commentf("%#v: %v", scenario, chg.Err())) var aliases []*backend.Alias var rmAliases []*backend.Alias switch scenario.mutation { case "-": case "add": aliases = []*backend.Alias{{"alias1", "alias-snap.cmd1"}} case "rm": rmAliases = []*backend.Alias{{"alias1", "alias-snap.cmd1"}} } comm := Commentf("%#v", scenario) expected := fakeOps{ { op: "update-aliases", aliases: aliases, rmAliases: rmAliases, }, { op: "matching-aliases", aliases: aliases, }, { op: "missing-aliases", aliases: rmAliases, }, { op: "update-aliases", aliases: rmAliases, rmAliases: aliases, }, } // start with an easier-to-read error if this fails: c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops(), comm) c.Assert(s.fakeBackend.ops, DeepEquals, expected, comm) var allAliases map[string]map[string]string err = s.state.Get("aliases", &allAliases) c.Assert(err, IsNil) if scenario.beforeStatus != "" { c.Check(allAliases, DeepEquals, map[string]map[string]string{ "alias-snap": {"alias1": scenario.beforeStatus}, }, comm) } else { c.Check(allAliases, HasLen, 0, comm) } s.fakeBackend.ops = nil } }