public void TestExtractPatch__NeedsUnsatisfiedPassSpecifier() { UrlDir.UrlConfig urlConfig = CreateConfig("@NODE_TYPE"); ITagList tagList = Substitute.For <ITagList>(); tagListParser.Parse("NODE_TYPE", urlConfig).Returns(tagList); IPassSpecifier passSpecifier = Substitute.For <IPassSpecifier>(); ProtoPatch protoPatch = new ProtoPatch( urlConfig, Command.Edit, "NODE_TYPE", "nodeName", "needs", "has", passSpecifier ); protoPatchBuilder.Build(urlConfig, Command.Edit, tagList).Returns(protoPatch); needsChecker.CheckNeedsExpression("needs").Returns(true); passSpecifier.CheckNeeds(needsChecker, progress).Returns(false); Assert.Null(patchExtractor.ExtractPatch(urlConfig)); AssertNoErrors(); Assert.Empty(root.AllConfigs); needsChecker.DidNotReceiveWithAnyArgs().CheckNeedsRecursive(null, null); patchCompiler.DidNotReceiveWithAnyArgs().CompilePatch(null); progress.DidNotReceiveWithAnyArgs().NeedsUnsatisfiedRoot(null); }
public void TestCompilePatch__Insert() { ProtoPatch protoPatch = new ProtoPatch( UrlBuilder.CreateConfig(new TestConfigNode("NODEE") { { "name", "foo" }, { "bar", "bleh" }, }, file), Command.Insert, "NODE", "foo", null, "#bar", Substitute.For <IPassSpecifier>() ); InsertPatch patch = Assert.IsType <InsertPatch>(patchCompiler.CompilePatch(protoPatch)); Assert.Same(protoPatch.urlConfig, patch.UrlConfig); LinkedList <IProtoUrlConfig> configs = new LinkedList <IProtoUrlConfig>(); patch.Apply(configs, progress, logger); Assert.Equal(1, configs.Count); Assert.NotSame(protoPatch.urlConfig.config, configs.First.Value.Node); AssertNodesEqual(new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "bleh" }, }, configs.First.Value.Node); Assert.Same(file, configs.First.Value.UrlFile); }
public void TestCompilePatch__Delete() { ProtoPatch protoPatch = new ProtoPatch( UrlBuilder.CreateConfig("ghi/jkl", new ConfigNode("-NODE")), Command.Delete, "NODE", "foo", null, "#bar", Substitute.For <IPassSpecifier>() ); DeletePatch patch = Assert.IsType <DeletePatch>(patchCompiler.CompilePatch(protoPatch)); Assert.Same(protoPatch.urlConfig, patch.UrlConfig); AssertNodeMatcher(patch.NodeMatcher); UrlDir.UrlConfig urlConfig = UrlBuilder.CreateConfig(new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "baz" }, }, file); patch.Apply(file, progress, logger); AssertNoErrors(); progress.Received().ApplyingDelete(urlConfig, protoPatch.urlConfig); Assert.Equal(0, file.configs.Count); }
public void TestCompilePatch__Copy() { ProtoPatch protoPatch = new ProtoPatch( UrlBuilder.CreateConfig("ghi/jkl", new TestConfigNode("+NODE") { { "@name", "boo" }, { "@bar", "bleh" }, }), Command.Copy, "NODE", "foo", null, "#bar", Substitute.For <IPassSpecifier>() ); CopyPatch patch = Assert.IsType <CopyPatch>(patchCompiler.CompilePatch(protoPatch)); Assert.Same(protoPatch.urlConfig, patch.UrlConfig); AssertNodeMatcher(patch.NodeMatcher); ConfigNode config = new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "baz" }, }; IProtoUrlConfig urlConfig = Substitute.For <IProtoUrlConfig>(); urlConfig.Node.Returns(config); urlConfig.UrlFile.Returns(file); LinkedList <IProtoUrlConfig> configs = new LinkedList <IProtoUrlConfig>(); configs.AddLast(urlConfig); patch.Apply(configs, progress, logger); AssertNoErrors(); progress.Received().ApplyingCopy(urlConfig, protoPatch.urlConfig); IProtoUrlConfig[] newConfigs = configs.ToArray(); Assert.Equal(2, newConfigs.Length); Assert.Same(config, newConfigs[0].Node); AssertNodesEqual(new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "baz" }, }, newConfigs[0].Node); AssertNodesEqual(new TestConfigNode("NODE") { { "name", "boo" }, { "bar", "bleh" }, }, newConfigs[1].Node); Assert.Same(file, newConfigs[1].UrlFile); }
public void TestExtractPatch__Insert() { UrlDir.UrlConfig urlConfig = CreateConfig("NODE_TYPE"); ITagList tagList = Substitute.For <ITagList>(); tagListParser.Parse("NODE_TYPE", urlConfig).Returns(tagList); IPassSpecifier passSpecifier = Substitute.For <IPassSpecifier>(); ProtoPatch protoPatch = new ProtoPatch( urlConfig, Command.Insert, "NODE_TYPE", null, "needs", null, passSpecifier ); protoPatchBuilder.Build(urlConfig, Command.Insert, tagList).Returns(protoPatch); needsChecker.CheckNeedsExpression("needs").Returns(true); passSpecifier.CheckNeeds(needsChecker, progress).Returns(true); ConfigNode needsCheckedNode = null; needsChecker.CheckNeedsRecursive(Arg.Do <ConfigNode>(node => needsCheckedNode = node), urlConfig); Assert.Null(patchExtractor.ExtractPatch(urlConfig)); AssertNoErrors(); Received.InOrder(delegate { tagListParser.Parse("NODE_TYPE", urlConfig); protoPatchBuilder.Build(urlConfig, Command.Insert, tagList); needsChecker.CheckNeedsExpression("needs"); passSpecifier.CheckNeeds(needsChecker, progress); needsChecker.CheckNeedsRecursive(needsCheckedNode, urlConfig); }); patchCompiler.DidNotReceiveWithAnyArgs().CompilePatch(null); Assert.Equal(1, root.AllConfigs.Count()); UrlDir.UrlConfig newUrlConfig = root.AllConfigs.First(); Assert.NotSame(urlConfig, newUrlConfig); Assert.NotSame(urlConfig.config, newUrlConfig.config); AssertConfigNodesEqual(urlConfig.config, newUrlConfig.config); Assert.Same(needsCheckedNode, newUrlConfig.config); progress.DidNotReceiveWithAnyArgs().NeedsUnsatisfiedRoot(null); }
public void TestCompilePatch__Edit() { ProtoPatch protoPatch = new ProtoPatch( UrlBuilder.CreateConfig("ghi/jkl", new TestConfigNode("@NODE") { { "@bar", "bleh" }, }), Command.Edit, "NODE", "foo", null, "#bar", Substitute.For <IPassSpecifier>() ); EditPatch patch = Assert.IsType <EditPatch>(patchCompiler.CompilePatch(protoPatch)); Assert.Same(protoPatch.urlConfig, patch.UrlConfig); AssertNodeMatcher(patch.NodeMatcher); ConfigNode config = new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "baz" }, }; IProtoUrlConfig urlConfig = Substitute.For <IProtoUrlConfig>(); urlConfig.Node.Returns(config); urlConfig.UrlFile.Returns(file); LinkedList <IProtoUrlConfig> configs = new LinkedList <IProtoUrlConfig>(); configs.AddLast(urlConfig); patch.Apply(configs, progress, logger); AssertNoErrors(); progress.Received().ApplyingUpdate(urlConfig, protoPatch.urlConfig); Assert.Single(configs); Assert.NotSame(config, configs.First.Value.Node); AssertNodesEqual(new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "bleh" }, }, configs.First.Value.Node); Assert.Same(file, configs.First.Value.UrlFile); }
public void TestCompilePatch__Copy() { ProtoPatch protoPatch = new ProtoPatch( UrlBuilder.CreateConfig("ghi/jkl", new TestConfigNode("+NODE") { { "@name", "boo" }, { "@bar", "bleh" }, }), Command.Copy, "NODE", "foo", null, "#bar", Substitute.For <IPassSpecifier>() ); CopyPatch patch = Assert.IsType <CopyPatch>(patchCompiler.CompilePatch(protoPatch)); Assert.Same(protoPatch.urlConfig, patch.UrlConfig); AssertNodeMatcher(patch.NodeMatcher); UrlDir.UrlConfig urlConfig = UrlBuilder.CreateConfig(new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "baz" }, }, file); patch.Apply(file, progress, logger); AssertNoErrors(); progress.Received().ApplyingCopy(urlConfig, protoPatch.urlConfig); Assert.Equal(2, file.configs.Count); Assert.Same(urlConfig, file.configs[0]); AssertNodesEqual(new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "baz" }, }, file.configs[0].config); AssertNodesEqual(new TestConfigNode("NODE") { { "name", "boo" }, { "bar", "bleh" }, }, file.configs[1].config); }
public void TestCompilePatch__InvalidCommand__Special() { ProtoPatch protoPatch = new ProtoPatch( UrlBuilder.CreateConfig("ghi/jkl", new ConfigNode()), Command.Special, "NODE", "foo", null, "#bar", Substitute.For <IPassSpecifier>() ); ArgumentException ex = Assert.Throws <ArgumentException>(delegate { patchCompiler.CompilePatch(protoPatch); }); Assert.Equal("protoPatch", ex.ParamName); Assert.Contains("invalid command for a root node: Special", ex.Message); }
public void TestCompilePatch__Delete() { ProtoPatch protoPatch = new ProtoPatch( UrlBuilder.CreateConfig("ghi/jkl", new ConfigNode("-NODE")), Command.Delete, "NODE", "foo", null, "#bar", Substitute.For <IPassSpecifier>() ); DeletePatch patch = Assert.IsType <DeletePatch>(patchCompiler.CompilePatch(protoPatch)); Assert.Same(protoPatch.urlConfig, patch.UrlConfig); AssertNodeMatcher(patch.NodeMatcher); IProtoUrlConfig urlConfig = Substitute.For <IProtoUrlConfig>(); urlConfig.Node.Returns(new TestConfigNode("NODE") { { "name", "foo" }, { "bar", "baz" }, }); LinkedList <IProtoUrlConfig> configs = new LinkedList <IProtoUrlConfig>(); configs.AddLast(urlConfig); patch.Apply(configs, progress, logger); AssertNoErrors(); progress.Received().ApplyingDelete(urlConfig, protoPatch.urlConfig); Assert.Empty(configs); }
public IPatch ExtractPatch(UrlDir.UrlConfig urlConfig) { if (urlConfig == null) { throw new ArgumentNullException(nameof(urlConfig)); } try { if (!urlConfig.type.IsBracketBalanced()) { progress.Error(urlConfig, "Error - node name does not have balanced brackets (or a space - if so replace with ?):\n" + urlConfig.SafeUrl()); return(null); } Command command = CommandParser.Parse(urlConfig.type, out string name); if (command == Command.Replace) { progress.Error(urlConfig, $"Error - replace command (%) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Create) { progress.Error(urlConfig, $"Error - create command (&) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Rename) { progress.Error(urlConfig, $"Error - rename command (|) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Paste) { progress.Error(urlConfig, $"Error - paste command (#) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Special) { progress.Error(urlConfig, $"Error - special command (*) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } ITagList tagList; try { tagList = tagListParser.Parse(name, urlConfig); } catch (FormatException ex) { progress.Error(urlConfig, $"Cannot parse node name as tag list: {ex.Message}\non: {urlConfig.SafeUrl()}"); return(null); } ProtoPatch protoPatch = protoPatchBuilder.Build(urlConfig, command, tagList); if (protoPatch == null) { return(null); } if (protoPatch.needs != null && !needsChecker.CheckNeedsExpression(protoPatch.needs)) { progress.NeedsUnsatisfiedRoot(urlConfig); return(null); } else if (!protoPatch.passSpecifier.CheckNeeds(needsChecker, progress)) { return(null); } needsChecker.CheckNeedsRecursive(urlConfig.config, urlConfig); return(patchCompiler.CompilePatch(protoPatch)); } catch (Exception e) { progress.Exception(urlConfig, $"Exception while attempting to create patch from config: {urlConfig.SafeUrl()}", e); return(null); } }