private void TestNodeBuilder(List <RowEntry> peptideProteinMapList, IReadOnlyList <string> expectedOutput)
        {
            var nodeBuilder   = new NodeBuilder();
            var nodeCollapser = new NodeCollapser();
            var dfs           = new DFS();
            var cover         = new Cover();

            var globalIDTracker = new GlobalIDContainer();

            nodeBuilder.RunAlgorithm(peptideProteinMapList, out var proteins, out var peptides);

            nodeCollapser.RunAlgorithm(proteins, peptides, globalIDTracker);

            var proteinsWithChildren = proteins.Values.ToList();
            var clusteredProteinSets = dfs.RunAlgorithm(proteinsWithChildren);
            var clusteredProteins    = cover.RunAlgorithm(clusteredProteinSets);

            var outLines = Utilities.ConvertNodesToStringList(clusteredProteins, globalIDTracker);

            foreach (var item in outLines)
            {
                Console.WriteLine(item);
            }

            if (expectedOutput == null || expectedOutput.Count == 0)
            {
                return;
            }

            for (var i = 0; i < outLines.Count; i++)
            {
                if (i >= expectedOutput.Count)
                {
                    Assert.Fail("Extra, unexpected output line: " + outLines[i]);
                }

                Assert.AreEqual(expectedOutput[i], outLines[i], "Mismatch on line {0}", i + 1);
            }

            if (expectedOutput.Count > outLines.Count)
            {
                Assert.Fail("Output did not include additional, expected lines, starting with " + expectedOutput[outLines.Count]);
            }
        }
        /// <summary>
        /// Group proteins having similar peptides
        /// </summary>
        /// <returns></returns>
        private void PerformParsimonyWork()
        {
            mProcessingSucceeded = false;
            mClusteredProteins   = new List <Node>();
            mGlobalIDTracker     = new GlobalIDContainer();

            // Prepare objects and algorithms
            var nodeBuilder   = new NodeBuilder();
            var nodeCollapser = new NodeCollapser();

            var dfs = new DFS {
                MaxRecursionDepth = mMaxDFSRecursionDepth
            };

            var cover = new Cover();

            RegisterEvents(dfs);
            RegisterEvents(cover);

            if (ShowProgressAtConsole)
            {
                Console.WriteLine();
                OnStatusEvent("Finding parsimonious protein groups");
            }

            nodeBuilder.RunAlgorithm(mPeptideProteinMapList, out var proteins, out var peptides);

            if (proteins == null || proteins.Count == 0)
            {
                throw new Exception("Error in PerformParsimony: Protein list is empty");
            }

            if (peptides == null || peptides.Count == 0)
            {
                throw new Exception("Error in PerformParsimony: Peptide list is empty");
            }

            nodeCollapser.RunAlgorithm(proteins, peptides, mGlobalIDTracker);

            if (proteins == null || proteins.Count == 0)
            {
                throw new Exception("Error in PerformParsimony after nodeCollapser.RunAlgorithm: Protein list is empty");
            }

            if (peptides == null || peptides.Count == 0)
            {
                throw new Exception("Error in PerformParsimony after nodeCollapser.RunAlgorithm: Peptide list is empty");
            }

            var proteinsWithChildren = proteins.Values.ToList();

            var clusteredProteinSets = dfs.RunAlgorithm(proteinsWithChildren);

            if (clusteredProteinSets == null || clusteredProteinSets.Count == 0)
            {
                throw new Exception("Error in PerformParsimony: DFS returned an empty protein list");
            }

            mClusteredProteins = cover.RunAlgorithm(clusteredProteinSets);

            if (mClusteredProteins == null || mClusteredProteins.Count == 0)
            {
                throw new Exception("Error in PerformParsimony: cover.RunAlgorithm returned an empty protein list");
            }

            if (ShowProgressAtConsole)
            {
                OnStatusEvent("Iteration Complete, found {0} protein groups", mClusteredProteins.Count);
            }

            mProcessingSucceeded = true;
        }