internal override bool FixElement(XElement rt, FwDataFixer.ErrorLogger errorLogger) { var xaClass = rt.Attribute("class").Value; switch (xaClass) { case "StStyle": var guid = rt.Attribute("guid").Value; if (!m_deletedGuids.Contains(guid)) return true; // keep it as far as we're concerned. var name = rt.Element("Name").Element("Uni").Value; // none can be null or we wouldn't have listed it for deletion errorLogger(String.Format(Strings.ksRemovingDuplicateStyle, name), true); return false; // This element must go away! case "LangProject": case "Scripture": var styles = rt.Element("Styles"); if (styles == null) return true; // Removing these here prevents additional error messages about missing objects, since the // targets of these objsurs are no longer present. foreach (var objsur in styles.Elements().ToArray()) // ToArray so as not to modify collection we're iterating over { var surGuid = objsur.Attribute("guid").Value; if (m_deletedGuids.Contains(surGuid)) objsur.Remove(); } break; } return true; // we're not deleting it. }
internal override bool FixElement(XElement rt, FwDataFixer.ErrorLogger logger) { var classAttr = rt.Attribute("class"); if (classAttr == null) return true; // bizarre, but leave it alone List<string> requiredFields; if (!m_customFields.TryGetValue(classAttr.Value, out requiredFields)) return true; // has no custom fields we care about var missingFields = new HashSet<string>(requiredFields); foreach (var child in rt.Elements()) { if (child.Name == "Custom") { var nameAttr = child.Attribute("name"); if (nameAttr != null) missingFields.Remove(nameAttr.Value); // not missing, we don't need to add it. } } foreach (var fieldName in missingFields) { rt.Add(new XElement("Custom", new XAttribute("name", fieldName), new XAttribute("val", "0"))); var guid = rt.Attribute("guid").Value; // This is such an insignificant fix from the user's point of view that we might prefer not // even to report it. But don't remove the logging without adding another mechanism for // the system to know that a problem has been fixed...this controls the important behavior // of re-splitting the file before we commit. logger(guid, DateTime.Now.ToShortDateString(), String.Format(Strings.ksAddingMissingDefaultForValueType, guid)); } return true; }
private static int Main(string[] args) { SetUpErrorHandling(); var pathname = args[0]; using (var prog = new LoggingProgress()) { var data = new FwDataFixer(pathname, prog, logError, getErrorCount); data.FixErrorsAndSave(); } return errorsOccurred ? 1 : 0; }
private static int Main(string[] args) { SetUpErrorHandling(); var pathname = args[0]; using (var prog = new NullProgress()) { var data = new FwDataFixer(pathname, prog, logger); data.FixErrorsAndSave(); } if (errorsOccurred) return 1; return 0; }
internal override bool FixElement(XElement rt, FwDataFixer.ErrorLogger logger) { var guid = new Guid(rt.Attribute("guid").Value); var xaClass = rt.Attribute("class"); var className = xaClass == null ? "<unknown>" : xaClass.Value; var customProperties = GetAllCustomProperties(rt); foreach (var kvp in customProperties) { if (!string.IsNullOrEmpty(kvp.Key) && m_customFieldNames.ContainsKey(kvp.Key)) continue; logger(String.Format(Strings.ksRemovingUndefinedCustomProperty, kvp.Key.Substring(0, kvp.Key.LastIndexOf('_')), className, guid), true); kvp.Value.Remove(); } return true; }
private object FixDataFile(IProgress progressDlg, params object[] parameters) { string pathname = parameters[0] as string; StringBuilder bldr = new StringBuilder(); FwDataFixer data = new FwDataFixer(pathname, progressDlg, LogErrors); data.FixErrorsAndSave(); foreach (var err in errors) { bldr.AppendLine(err); } return(bldr.ToString()); }
/// <summary> /// This is the main routine that does actual repair on list names. /// </summary> /// <param name="rt"></param> /// <param name="logger"></param> /// <returns>true (always, currently) to indicate that the list should survive.</returns> internal override bool FixElement(XElement rt, FwDataFixer.ErrorLogger logger) { var guid = rt.Attribute("guid").Value; string name; if (!m_guidToName.TryGetValue(guid, out name)) return true; // we didn't see a list with this guid; do nothing string firstGuid = m_nameToGuid[name]; if (firstGuid == guid) return true; // This one is allowed to keep this name int append = 1; string fixedName = name + append; while (m_nameToGuid.ContainsKey(fixedName)) fixedName = name + append++; m_nameToGuid[fixedName] = guid; // this name is now taken too. rt.Element("Name").Element("AUni").SetValue(fixedName); logger(String.Format(Strings.ksRepairingDuplicateListName, name, firstGuid, guid, fixedName), true); return true; }
public void TestEntryWithOneExtraMsaAndOneSenseWithABustedRef() { var testPath = Path.Combine(basePath, "EntryExtraMsaAndBustedSenseRef"); _errors.Clear(); Assert.DoesNotThrow(() => { var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); // SUT data.FixErrorsAndSave(); }, "Exception running the data fixer on the entry with MSA and no senses test data."); Assert.That(_errors.Count, Is.GreaterThan(0), "fixing anything should log an error"); // check that the msa was there originally AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]/MorphoSyntaxAnalyses/objsur", 2, false); // And that it was deleted. AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]/MorphoSyntaxAnalyses/objsur", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\"]/MorphoSyntaxAnalysis/objsur", 1, false); }
public void TestForEmptySequences() { // Setup var testPath = Path.Combine(basePath, "SequenceFixer"); // This rt element is a clause marker that has no dependent clauses // and so should be deleted from its chart. const string clauseMarkerGuid = "c4e487c6-bbbe-4b8f-8137-7d5fa7d2dc09"; // This rt element will have no component cells after the above clause marker is deleted // and so it also should be deleted from its chart. const string chartRowGuid = "6d9fe079-df9c-40c6-9cec-8e1dc1bbda92"; // This is the row's chart (owner). const string chartGuid = "8fa53cdf-9950-4a23-ba1c-844723c2342d"; // This rt element holds a sequence of phonetic contexts that is empty // and so should be deleted from its rule. const string sequenceContextGuid = "09acafc4-33fd-4c12-a96d-af0d87c343d0"; // This is the sequence context's owner. const string segmentRuleRhsGuid = "bd72b1c5-3067-433d-980d-5aae9271556d"; Assert.DoesNotThrow(() => { var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); // SUT data.FixErrorsAndSave(); }, "Exception running the data fixer on the sequence test data."); // Verification // check that the clause marker was there originally AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"ConstChartClauseMarker\" and @guid=\"" + clauseMarkerGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + chartRowGuid + "\"]", 1, false); // check that the clause marker has been deleted AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"ConstChartClauseMarker\" and @guid=\"" + clauseMarkerGuid + "\"]", 0, false); // check that the row is no longer in the chart AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + chartRowGuid + "\"]", 0, false); // check that the row has been deleted AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"ConstChartRow\" and @guid=\"" + chartRowGuid + "\"]", 0, false); // check that the phone rule sequence context was there originally AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"PhSequenceContext\" and @guid=\"" + sequenceContextGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + segmentRuleRhsGuid + "\"]", 1, false); // check that the phone rule sequence context has been deleted AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"PhSequenceContext\" and @guid=\"" + sequenceContextGuid + "\"]", 0, false); Assert.AreEqual(3, _errors.Count, "Unexpected number of errors found."); Assert.AreEqual("Removing owner of empty sequence (guid='" + chartRowGuid + "' class='ConstChartRow') from its owner (guid='" + chartGuid + "').", _errors[0], "Error message is incorrect.");//SequenceFixer--ksRemovingOwnerOfEmptySequence Assert.AreEqual("Removing owner of empty sequence (guid='" + clauseMarkerGuid + "' class='ConstChartClauseMarker') from its owner (guid='" + chartRowGuid + "').", _errors[1], "Error message is incorrect.");//SequenceFixer--ksRemovingOwnerOfEmptySequence Assert.AreEqual("Removing owner of empty sequence (guid='" + sequenceContextGuid + "' class='PhSequenceContext') from its owner (guid='" + segmentRuleRhsGuid + "').", _errors[2], "Error message is incorrect.");//SequenceFixer--ksRemovingOwnerOfEmptySequence }
public void TestEntryWithExtraMSA() { var testPath = Path.Combine(basePath, "EntryWithExtraMSA"); _errors.Clear(); Assert.DoesNotThrow(() => { var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); // SUT data.FixErrorsAndSave(); }, "Exception running the data fixer on the entry with extra MSA test data."); Assert.That(_errors.Count, Is.GreaterThan(0), "fixing anything should log an error"); // check that the clause marker was there originally AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]/MorphoSyntaxAnalyses/objsur", 4, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"MoStemMsa\"]", 5, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"FsFeatStruc\"]", 2, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"FsComplexValue\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"FsClosedValue\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]/MorphoSyntaxAnalyses/objsur", 2, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"MoStemMsa\"]", 3, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"FsFeatStruc\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"FsComplexValue\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"FsClosedValue\"]", 0, false); }
public void TestDanglingCustomProperty() { var testPath = Path.Combine(basePath, "DanglingCustomProperty"); // This test checks that dangling custom properties left by an edit/delete conflict // when a custom list is deleted are identified and removed // and that an error message is produced for them. const string danglingPropertyName = "Nonexistent"; const string custItem1Guid = "ee90ab2a-cf14-47e4-b49d-83d967447b65"; // guid referenced inside the dangler const string custItem2Guid = "0f2d36b5-504b-462a-9004-4ded018a89d1"; const string entryGuid = "efc0f898-7a52-4fe4-b827-f87a348e1b4b"; // dangling property should be removed from this rt element var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]", 2, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]/Custom[@name=\"" + danglingPropertyName + "\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + custItem2Guid + "\"]", 1, false); Assert.AreEqual(2, _errors.Count, "Unexpected number of errors found."); Assert.True(_errors[0].StartsWith("Removing dangling link to '" + custItem1Guid + "' (class='LexEntry'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject Assert.That(_errors[1], Is.StringStarting("Removing undefined custom property '" + danglingPropertyName + "' from class='LexEntry', guid='" + entryGuid + "'."), "Error message is incorrect."); // CustomPropertyFixer--ksRemovingUndefinedCustomProperty // Note that we don't currently get an error about deleting the FIRST dangling custom property, // because it is also a dangling reference, and hence gets deleted before the custom prop code // sees it. They could equally be checked in the opposite order, in which case we would get // two dangling property and no dangling ref messages. // Check original errors AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + custItem1Guid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]/Custom[@name=\"" + danglingPropertyName + "\"]", 2, false); }
public void TestDuplicateWritingSystems() { var testPath = Path.Combine(basePath, "DuplicateWs"); // Looks for duplicate AStr elements with the same writing system (english) and makes sure the Fixer fixes 'em up. const string testGuid = "00041516-72d1-4e56-9ed8-fe235a9b1a68"; var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"CmSemanticDomain\" and @guid=\"" + testGuid + "\"]//Description/AStr[@ws=\"en\"]", 1, false); Assert.AreEqual(1, _errors.Count, "Incorrect number of errors."); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"CmSemanticDomain\" and @guid=\"" + testGuid + "\"]//Description/AStr[@ws=\"en\"]", 2, false); }
public void DuplicateNameCustomLists_OneIsRenamed() { var testPath = Path.Combine(basePath, "DuplicateNameCustomList"); var fixedDataPath = Path.Combine(testPath, "BasicFixup.fwdata"); var originalFwData = File.ReadAllText(fixedDataPath); var data = new FwDataFixer(fixedDataPath, new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); // Read the file data into memory once. var backupFwData = File.ReadAllText(Path.Combine(testPath, "BasicFixup.bak")); var fixedFwData = File.ReadAllText(fixedDataPath); Assert.AreEqual(originalFwData, backupFwData, "backup file should preserve original (bad) data"); Assert.AreNotEqual(originalFwData, fixedFwData, "fixing data should have changed something!"); // Verify initial state: two lists with the same name. AssertThatXmlIn.String(backupFwData).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='CmPossibilityList']/Name/AUni[text()='Custom test list']", 2, false); // Verify output: two lists with original IDs and second is renamed. AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='CmPossibilityList' and @guid='5250350b-83fb-432b-a24f-a8dad580d350']/Name/AUni[text()='Custom test list']", 1, false); AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='CmPossibilityList' and @guid='1e4c4389-7835-408f-9408-c7f1c488d737']/Name/AUni[text()='Custom test list1']", 1, false); Assert.AreEqual(1, _errors.Count, "Unexpected number of errors found"); Assert.That(_errors[0], Is.EqualTo("Repairing duplicate lists both named \"Custom test list\". \"5250350b-83fb-432b-a24f-a8dad580d350\" kept the original name and \"1e4c4389-7835-408f-9408-c7f1c488d737\" was renamed to \"Custom test list1\""), "Error message is incorrect for dup."); }
public void TestDanglingCustomListReferences() { var testPath = Path.Combine(basePath, "DanglingCustomListReference"); // This test checks that dangling reference guids left by an edit/delete conflict // when a custom list item is deleted are identified and removed // and that an error message is produced for them. const string custItem1Guid = "ee90ab2a-cf14-47e4-b49d-83d967447b65"; // the dangler const string custItem2Guid = "0f2d36b5-504b-462a-9004-4ded018a89d1"; var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + custItem1Guid + "\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + custItem2Guid + "\"]", 1, false); // The containing <Custom> element as well as the objsur should be removed AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@guid='c5e6aab3-4236-43b4-998e-d41ff26eba7b']/Custom", 0, false); Assert.AreEqual(1, _errors.Count, "Unexpected number of errors found."); Assert.True(_errors[0].StartsWith("Removing dangling link to '" + custItem1Guid + "' (class='LexEntry'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject // Check original errors AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + custItem1Guid + "\"]", 1, false); }
public void TestForHomographNumberInconsistency() { // Setup var testPath = Path.Combine(basePath, "HomographFixer"); // LexEntries needing homograph number set to 1 or 2 const string lexEntry_dinding1Guid = "a39f2112-b82c-46ba-9f69-6b46e45efff4"; const string lexEntry_dinding2Guid = "b35e8d52-e74d-47b4-b300-82e8c45cdfb7"; const string emptyEntry1Guid = "2B5C8394-A9BD-4873-8D7D-25C97DF72ACD"; const string emptyEntry2Guid = "49E8B5A0-3D68-4544-BBB6-195EEC5CA367"; const string emptyEntry3Guid = "1ABB7D7B-86C1-4811-B5AD-6A776AD1BADF"; const string emptyEntry4Guid = "984DBC2D-B482-4A91-B250-DC0858DF14FD"; const string homoSomethingGuid = "972EAFEA-49D6-40D7-A848-6E658C1A2A79"; // h**o in de, something in fr const string homoElseGuid = "9BE4E7C0-BDF2-40A5-98E3-70E42D955C49"; // h**o in de, else in fr const string irrelevantElseGuid = "A42984AA-EEA0-4204-AC81-9B9B115E9785"; // irrelevant in de, else in fr const string citationDiffGuid1 = "21122112-bad1-46ba-9f69-6b46e45efff4"; const string citationDiffGuid2 = "21122112-bad2-46ba-9f69-6b46e45efff4"; const string citationSameGuid1 = "33333333-bad1-46ba-9f69-6b46e45efff4"; const string citationSameGuid2 = "33333333-bad2-46ba-9f69-6b46e45efff4"; const string sameSecondaryOrder1 = "ABABABAA-EEA0-4204-AC81-9B9B115E9785"; const string sameSecondaryOrder2 = "EBEAEBEA-EEA0-4204-AC81-9B9B115E9785"; const string diffSecondaryOrder = "FABFABFA-EEA0-4204-AC81-9B9B115E9785"; // Verification of input. var testFile = Path.Combine(testPath, "BasicFixup.fwdata"); // It's important that one of the entries needing a non-zero number does not have one at all to begin with. AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\" and @guid=\"" + lexEntry_dinding1Guid + "\" and not(HomographNumber)]", 1, false); // It's also important that one of them has allmorphs AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexEntry\" and @guid=\"" + lexEntry_dinding2Guid + "\" and AlternateForms/objsur/@guid='bb464c5d-de15-494b-bc05-1ee92c3028e6']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + lexEntry_dinding1Guid + "']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + "08fc938e-110e-44f4-8660-165d26030124" + "']", 1, false); // Group of four entries that have empty lexeme form. We want them to end up with no homograph numbers. AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + emptyEntry1Guid + "']/HomographNumber[@val='1']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + emptyEntry2Guid + "']/HomographNumber[@val='2']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + emptyEntry3Guid + "']/HomographNumber[@val='3']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + emptyEntry4Guid + "']", 1, false); // The third has no LexemeForm field at all. AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + emptyEntry3Guid + "']/LexemeForm", 0, false); // The fourth has no homograph number field at all. AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + emptyEntry4Guid + "']/HomographNumber", 0, false); // Two LexEntries have different citation forms but are otherwise identical starting with 0's should end with 0's AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + citationDiffGuid1 + "']/HomographNumber[@val='0']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + citationDiffGuid2 + "']/HomographNumber[@val='0']", 1, false); // Two LexEntries with the same citation forms but otherwise different starting with 0's should end with '1', '2' AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + citationSameGuid1 + "']/HomographNumber[@val='0']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + citationSameGuid2 + "']/HomographNumber[@val='0']", 1, false); // Two LexEntries have different SecondaryOrder in the MoMorphType but are otherwise identical // starting with 0's should end with a 0 and a the different should get a 1 AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + sameSecondaryOrder1 + "']/HomographNumber[@val='0']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + sameSecondaryOrder2 + "']/HomographNumber[@val='0']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='LexEntry' and @guid='" + diffSecondaryOrder + "']/HomographNumber[@val='0']", 1, false); // stems for multilingual ones: AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='" + "F417EEF7-8B30-4ED5-BF5A-BBD3A3FFB4C2" + "']/Form/AUni[@ws='de' and text()='irrelevant']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='" + "F417EEF7-8B30-4ED5-BF5A-BBD3A3FFB4C2" + "']/Form/AUni[@ws='fr' and text()='else']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='" + "AF2154B3-493E-47A7-B58F-285E2C39A16A" + "']/Form/AUni[@ws='de' and text()='h**o']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='" + "AF2154B3-493E-47A7-B58F-285E2C39A16A" + "']/Form/AUni[@ws='fr' and text()='else']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='" + "0F4FB8BF-AA48-4315-A244-B3B367DD0159" + "']/Form/AUni[@ws='de' and text()='h**o']", 1, false); AssertThatXmlIn.File(testFile).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='" + "0F4FB8BF-AA48-4315-A244-B3B367DD0159" + "']/Form/AUni[@ws='fr' and text()='something']", 1, false); _errors.Clear(); Assert.DoesNotThrow(() => { var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); // SUT data.FixErrorsAndSave(); }, "Exception running the data fixer on the sequence test data."); Assert.That(_errors.Count, Is.GreaterThan(0), "fixing anything should log an error"); var xmlDoc = GetResult(testFile); var entries = VerifyEntryExists(xmlDoc, "//rt[@class='LexEntry' and @guid='" + lexEntry_dinding1Guid + "']"); XmlNode entry = entries[0]; var homographEl = entry.SelectSingleNode("HomographNumber"); Assert.IsNotNull(homographEl); var homographAttribute = homographEl.Attributes[0]; Assert.IsTrue(homographAttribute.Name.ToString().Equals("val")); var homographVal1 = homographAttribute.Value; entries = VerifyEntryExists(xmlDoc, "//rt[@class='LexEntry' and @guid='" + lexEntry_dinding2Guid + "']"); entry = entries[0]; homographEl = entry.SelectSingleNode("HomographNumber"); Assert.IsNotNull(homographEl); homographAttribute = homographEl.Attributes[0]; Assert.IsTrue(homographAttribute.Name.ToString().Equals("val")); var homographVal2 = homographAttribute.Value; Assert.That((homographVal1 == "1" && homographVal2 == "2") || (homographVal1 == "2" && homographVal2 == "1"),"The homograph numbers were both zero for these LexEntries and should now be 1 and 2"); // Non-homograph should have HN corrected to zero. VerifyHn(xmlDoc, "08fc938e-110e-44f4-8660-165d26030124", "0"); // Set of messed up homographs should be fixed, and as far as possible, existing HNs should be preserved. // Technically, other outcomes are valid besides the one indicated here: the other entry that was previously 2 could keep that number, // and either the old zero or the other old 2 could be assigned 3 (and the other 4). But this is what currently happens. // Any changed algorithm should minimally (a) not change HN1; (b) keep HN2 for at least one of the entries that initially has it; // (c) produce HNs 1,2,3, and 4. VerifyHn(xmlDoc, "bb42e0a5-2131-4e2b-9c96-19a11c5a5081", "2"); // h**o that was previously 2 should still be VerifyHn(xmlDoc, "bb4042c7-47b2-422f-ae66-a09293d16ed8", "1"); // h**o that was previously 1 should still be VerifyHn(xmlDoc, "bb3d3349-5cea-4920-a2bc-672d5d927875", "3"); // h**o that was previously 0 should take next value VerifyHn(xmlDoc, "bb3be3bc-e4e6-4e72-9b1b-d81c0298b4e7", "4"); // h**o that was previously the second 2 should be changed //Two entries with different citation forms previously 0, should still be. VerifyHn(xmlDoc, citationSameGuid1, "1"); // former 0 should be 1 VerifyHn(xmlDoc, citationSameGuid2, "2"); // former 0 should be 2 VerifyHn(xmlDoc, citationDiffGuid1, "0"); // homograph# should be unchanged VerifyHn(xmlDoc, citationDiffGuid2, "0"); // homograph# should be unchanged VerifyHn(xmlDoc, sameSecondaryOrder1, "1"); // former 0 should be 1 VerifyHn(xmlDoc, diffSecondaryOrder, "0"); // homograph# should be unchanged VerifyHn(xmlDoc, sameSecondaryOrder2, "2"); // former 0 should be 2 VerifyHn(xmlDoc, emptyEntry1Guid, "0"); // entry with empty LF should have no HN VerifyHn(xmlDoc, emptyEntry2Guid, "0"); // entry with empty LF should have no HN VerifyHn(xmlDoc, emptyEntry3Guid, "0"); // entry with no LF should have no HN VerifyHn(xmlDoc, emptyEntry4Guid, null); // entry with empty LF and no previous HN element should still have none VerifyHn(xmlDoc, homoSomethingGuid, "0"); // not a homograph in french, though it is in the first AUni ws VerifyHn(xmlDoc, homoElseGuid, "1"); // a homograph in french VerifyHn(xmlDoc, irrelevantElseGuid, "2"); // a homograph in french (though not in the first AUni ws) }
/// <summary> /// This is the main routine that does actual repair on morph bundles. /// </summary> /// <param name="rt"></param> /// <param name="logger"></param> /// <returns>true (always, currently) to indicate that the bundle should survive.</returns> internal override bool FixElement(XElement rt, FwDataFixer.ErrorLogger logger) { var guidString = rt.Attribute("guid").Value; var xaClass = rt.Attribute("class"); if (xaClass == null) return true; // we can't fix it, anyway. var className = xaClass.Value; switch (className) { case "WfiMorphBundle": FixMsa(rt, logger, guidString); FixMorph(rt, logger, guidString); break; } return true; }
public void TestDanglingReferences() { var testPath = Path.Combine(basePath, "DanglingReference"); // This test checks that dangling references guids are identified and removed // and that an error message is produced for them. string testObjsurGuid = "aaaaaaaa-e15a-448e-a618-3855f93bd3c2"; string lexSenseGuid = "2210cf83-ad6c-47fe-91f8-8bf789473792"; string lexEntryGuid = "64cf9708-a7d4-4e1e-a403-deec87c34455"; string testChangeGuid = "cccccccc-a7d4-4e1e-a403-deec87c34455"; string secondDangler = "408ba7ca-e15a-448e-aaaa-3855f93bd3c2"; string partOfSpeechGuid = "4c90d669-cc98-49ea-8c9c-a739253336ed"; string parfOfSpeechOwnerGuid = "8e45de56-5105-48dc-b302-05985432e1e7"; var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + testObjsurGuid + "\"]", 0, false); Assert.AreEqual(4, _errors.Count, "Unexpected number of errors found."); Assert.True(_errors[0].StartsWith("Removing dangling link to '" + testObjsurGuid + "' (class='LexEntry'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject Assert.True(_errors[1].StartsWith("Changing ownerguid value from '" + testChangeGuid + "' to '" + lexEntryGuid + "' (class='LexSense', guid='" + lexSenseGuid), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject Assert.True(_errors[3].EndsWith("Removing object with nonexistent owner (invalid ownerguid='" + parfOfSpeechOwnerGuid + "', class='PartOfSpeech', guid='" + partOfSpeechGuid + "')."), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistentOwner Assert.True(_errors[2].StartsWith("Removing dangling link to '" + secondDangler + "' (class='LexSense'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject // The parent SenseType property of the danging <objsur> should be removed with it. AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\" and @guid=\"3110cf83-ad6c-47fe-91f8-8bf789473792\"]/SenseType", 0, false); // Check original errors AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"PartOfSpeech\" and @ownerguid=\"" + parfOfSpeechOwnerGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\" and @ownerguid=\"" + testChangeGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + testObjsurGuid + "\"]", 1, false); // Check that they were fixed AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"PartOfSpeech\" and @ownerguid=\"" + parfOfSpeechOwnerGuid + "\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\" and @ownerguid=\"" + lexEntryGuid + "\"]", 2, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + testObjsurGuid + "\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//SenseType/objsur[@guid=\"" + secondDangler + "\"]", 0, false); }
public void TestDuplicateStyles() { var testPath = Path.Combine(basePath, "DuplicateStyles"); // This test checks that styles with duplicate names are removed // and that an error message is produced for them. const string lpBob1 = "be765e3e-ea5e-11de-9d42-0013722f8dec"; const string lpBob2 = "d37394b7-d47c-4e3d-9f2a-d023fd6fef24"; string lpFred = "cea17237-b704-4bee-9a9b-1779d3108831"; const string lpBob3 = "d778dff3-36fb-4ddf-aa08-91827f2c22dc"; string scBob = "a89670f5-8d59-42ec-bfb5-10c63642b1dc"; const string scJoe1 = "ac48acc9-12f2-42c6-89dc-7d48870b7758"; const string scJoe2 = "ba7ffa0b-1beb-45fe-976a-c849cceb3026"; var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); // Make sure the original styles are present foreach (var guid in new[] {lpBob1, lpBob2, scJoe1, scJoe2}) { AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + guid + "\"]", 1, false); } AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + lpBob3 + "\"]", 2, false); Assert.AreEqual(4, _errors.Count, "Unexpected number of errors found."); //The order of these doesn't really matter but this is the one we happen to get. Assert.That(_errors[0], Is.EqualTo("Removing duplicate style Bob."), "Error message is incorrect."); Assert.That(_errors[1], Is.StringStarting("Removing dangling link to")); Assert.That(_errors[2], Is.EqualTo("Removing duplicate style Bob."), "Error message is incorrect."); Assert.That(_errors[3], Is.EqualTo("Removing duplicate style Joe."), "Error message is incorrect."); // These should survive foreach (var guid in new[] {lpBob1, lpFred, scJoe1, scBob}) { AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + guid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@guid=\"" + guid + "\"]", 1, false); } // These should not (the first xpath would match the reference to lpBob3 in fred as well as the owning one) foreach (var guid in new[] { lpBob2, lpBob3, scJoe2 }) { AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + guid + "\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@guid=\"" + guid + "\"]", 0, false); } }
public void TestDuplicateGuids() { var testPath = Path.Combine(basePath, "DuplicateGuid"); // This test checks that duplicate guids are identified and that an error message is produced for them. string testGuid = "2110cf83-ad6c-47fe-91f8-8bf789473792"; var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\" and @guid=\"" + testGuid + "\"]", 2, false); Assert.AreEqual(1, _errors.Count, "Unexpected number of errors found"); Assert.True(_errors[0].EndsWith("Object with guid '" + testGuid + "' already exists! (not fixed)"), "Error message is incorrect."); // OriginalFixer--ksObjectWithGuidAlreadyExists AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\" and @guid=\"" + testGuid + "\"]", 2, false); }
public void MissingBasicCustomField() { var testPath = Path.Combine(basePath, "MissingBasicCustomField"); var fixedDataPath = Path.Combine(testPath, "BasicFixup.fwdata"); var data = new FwDataFixer(fixedDataPath, new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); // Verify initial state: no custom field element on one input, the other already has them. AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='47ff8685-502a-4617-8ab7-9d27889b3b3f']/Custom", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='6c8f0104-dffb-43f3-9d1d-4c2ec2a4afa5']/Custom[@name='MyNumber' and @val='1']", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='6c8f0104-dffb-43f3-9d1d-4c2ec2a4afa5']/Custom[@name='MyDate' and @val='2']", 1, false); // Verify Results: the allomorph has had the expected basic custom fields added. AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='47ff8685-502a-4617-8ab7-9d27889b3b3f']/Custom[@name='MyNumber' and @val='0']", 1, false); AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='47ff8685-502a-4617-8ab7-9d27889b3b3f']/Custom[@name='MyDate' and @val='0']", 1, false); // The one that already had them should still only have one of each. AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='6c8f0104-dffb-43f3-9d1d-4c2ec2a4afa5']/Custom[@name='MyNumber' and @val='1']", 1, false); AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='6c8f0104-dffb-43f3-9d1d-4c2ec2a4afa5']/Custom[@name='MyDate' and @val='2']", 1, false); AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='6c8f0104-dffb-43f3-9d1d-4c2ec2a4afa5']/Custom[@name='MyNumber' and @val='0']", 0, false); AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='MoStemAllomorph' and @guid='6c8f0104-dffb-43f3-9d1d-4c2ec2a4afa5']/Custom[@name='MyDate' and @val='0']", 0, false); Assert.That(_errors[0], Is.StringStarting("Missing default value type added to ")); }
public void DuplicateWordforms_AreMerged() { var testPath = Path.Combine(basePath, WordformswithsameformTestDir); var fixedDataPath = Path.Combine(testPath, "BasicFixup.fwdata"); var data = new FwDataFixer(fixedDataPath, new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); // Test data has: // - Two wordforms with French form "dup". The second goes away, and its two analyses are moved to the first. // - a wordfom with a different French form ("other"). It is unaffected. // - a wordform with French form "dup", but also Spanish form "other". It is unaffected. // - two wordforms with French form "dupFr" and Spanish form "dupSp". The alternatives are in the opposite order. // Despite this they are merged, and the one Analysis of the second one is moved to the first, which // previously had none. // - a segment which references one of the deleted wordforms, and is changed to reference the replacement. var firstdupGuid = "64cf9708-a7d4-4e1e-a403-deec87c34455"; // First wordform with simple form "dup" var secondDupGuid = "0964665E-BB56-4406-8310-ADE04A7A23C7"; // Second with simple form "dup" var analysis2_1Guid = "86DB9E97-2E6C-4AAC-B78B-9EDA834254E7"; // first analysis of deleted wordform var analysis2_2Guid = "BCD9971A-D871-472D-8843-9B5392AAA57F"; // second analysis of deleted wordform VerifyElementCount(fixedDataPath, "WfiWordform", firstdupGuid, 1); // First "dup" should survive VerifyElementCount(fixedDataPath, "WfiWordform", secondDupGuid, 0); // Second "dup" should go away VerifyElementCount(fixedDataPath, "WfiWordform", "31EBCDB7-8274-4776-A6E0-1AB523AA9E1E", 1); // Non-dup should survive VerifyElementCount(fixedDataPath, "WfiWordform", "D596FD07-A4E6-4ED1-A859-7601ACD2CD36", 1); // Partial duplicate should survive VerifyElementCount(fixedDataPath, "WfiAnalysis", analysis2_1Guid, 1); // First analysis of deleted wordform should survive VerifyElementCount(fixedDataPath, "WfiAnalysis", analysis2_2Guid, 1); // Second analysis of deleted wordform should survive // The surviving analyses should have their owners corrected. I think it's enough to check one. AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='WfiAnalysis' and @guid='" + analysis2_2Guid + "' and @ownerguid='" + firstdupGuid + "']", 1, false); // The merged "dup" wordform should have four analyses AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='WfiWordform' and @guid='" + firstdupGuid + "']/Analyses/objsur", 4, false); // One of which should be the last one from the deleted wordform. AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='WfiWordform' and @guid='" + firstdupGuid + "']/Analyses/objsur[@guid='BCD9971A-D871-472D-8843-9B5392AAA57F']", 1, false); // The segment which refers to the deleted wordform should be fixed. AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='Segment' and @guid='b405f3c0-58e1-4492-8a40-e955774a6911']/Analyses/objsur[@guid='" + firstdupGuid + "']", 1, false); // Merging these two verifies that it does the right things when (a) the second word of a set is the only one with analyses // and (b) the writing systems are in a different order var firstDupFrSp = "83A4D906-3ED1-49D1-AA5D-FC2DB938B6A4"; VerifyElementCount(fixedDataPath, "WfiWordform", firstDupFrSp, 1); // first "dupFr/dupSp" should survive var secondDupSpFr = "D8444A90-A5CF-4163-B312-AFF577B0452E"; VerifyElementCount(fixedDataPath, "WfiWordform", secondDupSpFr, 0); // second "dupFr/dupSp" should go away // The second merged wordform should have one analysis AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='WfiWordform' and @guid='" + firstDupFrSp + "']/Analyses/objsur", 1, false); // The surviving analyses should have their owners corrected. I think it's enough to check one. AssertThatXmlIn.File(fixedDataPath).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class='WfiAnalysis' and @guid='AE2BA69A-42BA-4582-AFA4-B8AC3E5567C2' and @ownerguid='" + firstDupFrSp + "']", 1, false); Assert.AreEqual(2, _errors.Count, "Unexpected number of errors found"); Assert.That(_errors[0], Is.EqualTo("Wordform with guid '" + secondDupGuid + "' has same form (fr>dup) as '" + firstdupGuid + "' and was merged"), "Error message is incorrect for dup."); Assert.That(_errors[1], Is.EqualTo("Wordform with guid '" + secondDupSpFr + "' has same form (fr>dupFr&sp>dupSp) as '" + firstDupFrSp + "' and was merged"), "Error message is incorrect for dupSpFr."); // Check original errors. I think it's enough to verify that the two elements the merger was supposed to delete // were originally present. If the properties that allowed them to be merged were missing, it wouldn't happen. // If the components that get moved were not present, they would not show up in the fixed data. string backupPath = Path.Combine(testPath, "BasicFixup.bak"); // the original data we corrected VerifyElementCount(backupPath, "WfiWordform", secondDupGuid, 1); // Second "dup" was there originally. VerifyElementCount(backupPath, "WfiWordform", secondDupSpFr, 1); // second "dupFr/dupSp" was there originally. }
public void TestDanglingTextTagAndChartReferences() { var testPath = Path.Combine(basePath, "TagAndCellRefs"); // This test checks that dangling reference guids are identified and removed // and that an error message is produced for them. // It also checks that TextTags and ChartCells with missing references have been cleaned up. const string segmentGuid = "0157b3fd-b464-4983-a865-3eb9dbc7fa72"; // this Segment was deleted by the merge. // This ConstChartWordGroup references the Segment that went away. // Both BeginSegment and EndSegment are null (after Dangling Reference repair). // Delete the word group. const string chartCellGuid = "f864b36d-ecf0-4c22-9fac-ff91b009a8f8"; // This TextTag references the Segment that went away. // Its BeginSegment is still okay, but its EndSegment is bad. Dangling Reference repair will // delete the reference. Repair the tag. // At this point, the UI can't make a tag that references more than one Segment, but it may someday. const string textTagGuid = "fa0c3376-1dbc-42c0-b4ff-cd6bf0372b13"; const string chartRowGuid = "d2e52268-71bc-427e-a666-dbe66751b132"; const string chartGuid = "8fa53cdf-9950-4a23-ba1c-844723c2342d"; var dataFilePath = Path.Combine(testPath, "BasicFixup.fwdata"); var originalFwData = File.ReadAllText(dataFilePath); var data = new FwDataFixer(dataFilePath, new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); var backupFilePath = Path.Combine(testPath, "BasicFixup.bak"); var backupFwData = File.ReadAllText(backupFilePath); var fixedFwData = File.ReadAllText(dataFilePath); Assert.AreEqual(originalFwData, backupFwData, "backup file should preserve the original (bad) file content"); Assert.AreNotEqual(originalFwData, fixedFwData, "fixing data should have changed something!"); // Check initial state of the test file AssertThatXmlIn.String(originalFwData).HasSpecifiedNumberOfMatchesForXpath("//rt[@class=\"TextTag\"]", 1, false); AssertThatXmlIn.String(originalFwData).HasSpecifiedNumberOfMatchesForXpath("//rt[@class=\"ConstChartWordGroup\"]", 3, false); AssertThatXmlIn.String(originalFwData).HasSpecifiedNumberOfMatchesForXpath("//objsur[@guid=\"" + segmentGuid + "\"]", 3, false); AssertThatXmlIn.String(originalFwData).HasSpecifiedNumberOfMatchesForXpath("//rt[@class=\"ConstChartRow\" and @guid=\"" + chartRowGuid + "\"]", 1, false); // Check the repaired state of the test file AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath("//rt[@class=\"ConstChartRow\" and @guid=\"" + chartRowGuid + "\"]", 0, false); AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath("//rt[@class=\"TextTag\"]", 1, false); AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath("//rt[@class=\"ConstChartWordGroup\"]", 2, false); AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath("//objsur[@guid=\"" + segmentGuid + "\"]", 0, false); // got rid of all the refs to the bad segment. // The parent (property) elements of the deleted objsur elements should be gone, too. AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath( "//rt[@guid='f864b36d-ecf0-4c22-9fac-ff91b009a8f8']/BeginSegment", 0, false); AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath( "//rt[@guid='f864b36d-ecf0-4c22-9fac-ff91b009a8f8']/EndSegment", 0, false); // Note that the other dangling EndSegment does not result in the property being deleted; it is // repaired instead. // check that the row has been deleted AssertThatXmlIn.String(fixedFwData).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"ConstChartRow\" and @guid=\"" + chartRowGuid + "\"]", 0, false); Assert.AreEqual(7, _errors.Count, "Unexpected number of errors found."); Assert.True(_errors[0].StartsWith("Removing dangling link to '" + segmentGuid + "' (class='ConstChartWordGroup'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject Assert.True(_errors[1].StartsWith("Removing dangling link to '" + segmentGuid + "' (class='ConstChartWordGroup'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject Assert.True(_errors[2].StartsWith("Removing reference to missing Segment by deleting analysis object guid='" + chartCellGuid + "', class='ConstChartWordGroup'"), "Error message is incorrect."); // SequenceFixer--ksRemovingBadAnalysisRefObj Assert.True(_errors[3].StartsWith("Removing dangling link to '" + segmentGuid + "' (class='TextTag'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject Assert.True(_errors[4].EndsWith("changing analysis object guid='" + textTagGuid + "', class='TextTag', field='EndSegment'."), "Error message is incorrect."); // SequenceFixer--ksAdjustingAnalysisRefObj Assert.AreEqual("Removing owner of empty sequence (guid='" + chartRowGuid + "' class='ConstChartRow') from its owner (guid='" + chartGuid + "').", _errors[5], "Error message is incorrect.");//SequenceFixer--ksRemovingOwnerOfEmptySequence Assert.True(_errors[6].StartsWith("Removing dangling link to '"), "second pass removed a dangling link created by first pass"); }
/// <summary> /// Deal with problems of the Morph child, if any. /// </summary> /// <param name="rt"></param> /// <param name="logger"></param> /// <param name="guidString"></param> private void FixMorph(XElement rt, FwDataFixer.ErrorLogger logger, string guidString) { var destGuidString = ChildSurrogateGuid(rt, "Morph"); if (destGuidString == null) return; var objsur = rt.Element("Morph").Element("objsur"); // parts of path must exist, we got destGuidString if (m_guids.Contains(new Guid(destGuidString))) return; // all is well, not dangling. var senseGuid = ChildSurrogateGuid(rt, "Sense"); Guid entryGuid; XElement entryElt; if (senseGuid != null && m_owners.TryGetValue(new Guid(senseGuid), out entryGuid) && m_entrys.TryGetValue(entryGuid.ToString(), out entryElt)) { var soleForm = GetSoleForm(entryElt); if (soleForm != null) { // We can repair it to use the only form of the right entry, a very promising repair. objsur.SetAttributeValue("guid", soleForm); logger(guidString, DateTime.Now.ToShortDateString(), String.Format(Strings.ksRepairingBundleFormFromEntry, guidString)); return; } } // If we can't fix it nicely, just clobber it (and its parent, since this is an atomic property). logger(guidString, DateTime.Now.ToShortDateString(), String.Format(Strings.ksRemovingDanglingMorph, destGuidString, guidString)); objsur.Parent.Remove(); }
public void TestGenericDateFixup() { var fileLoc = Path.Combine(Path.Combine(basePath, "GenericDates"), "BasicFixup.fwdata"); var data = new FwDataFixer(fileLoc, new DummyProgressDlg(), LogErrors, ErrorCount); _errors.Clear(); data.FixErrorsAndSave(); Assert.That(_errors.Count, Is.GreaterThan(0), "fixing anything should log an error"); AssertThatXmlIn.File(fileLoc).HasSpecifiedNumberOfMatchesForXpath("//rt[@class='RnGenericRec']/DateOfEvent", 3); AssertThatXmlIn.File(fileLoc).HasAtLeastOneMatchForXpath("//rt[@class='RnGenericRec']/DateOfEvent[@val='0']"); }
//For each LexEntry element, set the homograph number as determined in the FinalFixerInitialization method. internal override bool FixElement(XElement rt, FwDataFixer.ErrorLogger logger) { var guidString = rt.Attribute("guid").Value; var guid = new Guid(guidString); var xaClass = rt.Attribute("class"); var className = xaClass == null ? kUnknown : xaClass.Value; switch (className) { case "LexEntry": string homographNum; if (!m_LexEntryHomographNumbers.TryGetValue(guid, out homographNum)) homographNum = "0"; // If it's not a homograph, its HN must be zero. var homographElement = rt.Element("HomographNumber"); if (homographElement == null) { if (homographNum != "0") // no need to make a change if already implicitly zero. { rt.Add(new XElement("HomographNumber", new XAttribute("val", homographNum))); logger(guidString, DateTime.Now.ToShortDateString(), String.Format(Strings.ksAdjustedHomograph, guidString, m_oldHomographNumbers[guid], homographNum)); } break; } if (homographElement.Attribute("val") == null || homographElement.Attribute("val").Value != homographNum) { homographElement.SetAttributeValue("val", homographNum); logger(guidString, DateTime.Now.ToShortDateString(), String.Format(Strings.ksAdjustedHomograph, guidString, m_oldHomographNumbers[guid], homographNum)); } break; default: break; } return true; }
private object FixDataFile(IProgress progressDlg, params object[] parameters) { string pathname = parameters[0] as string; StringBuilder bldr = new StringBuilder(); FwDataFixer data = new FwDataFixer(pathname, progressDlg, LogErrors); data.FixErrorsAndSave(); foreach (var err in errors) bldr.AppendLine(err); return bldr.ToString(); }
public void TestDanglingSenseAndBundleLink() { var testPath = Path.Combine(basePath, "DeletedMsaRefBySenseAndBundle"); var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); var danglingMsaGuid = "aaaaaaaa-e15a-448e-a618-3855f93bd3c2"; // nonexistent 'msa' var bundleGuid = "10f3db1e-33db-4d9d-9a06-e0a8e1ed8a92"; var senseGuid = "3110cf83-ad6c-47fe-91f8-8bf789473792"; // Verify initial state. // We start out with a morph bundles and a sense that have broken links to the same missing MSA. AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + bundleGuid + "\"]/Msa/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\" and @guid=\"" + senseGuid + "\"]/MorphoSyntaxAnalysis/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); // Check errors Assert.AreEqual(2, _errors.Count, "Unexpected number of errors found."); Assert.True(_errors[0].StartsWith("Removing dangling link to '" + danglingMsaGuid + "' (class='LexSense'"), "Error message is incorrect."); Assert.That(_errors[1], Is.EqualTo("Removing dangling link to MSA '" + danglingMsaGuid + "' for WfiMorphBundle '" + bundleGuid + "'."), "Error message is incorrect."); // MorphBundleFixer--ksRemovingDanglingMsa // Check file repair AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + bundleGuid + "\"]/Msa", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexSense\" and @guid=\"" + senseGuid + "\"]/MorphoSyntaxAnalysis", 0, false); }
public void TestSingleTargetLexReferences() { var testPath = Path.Combine(basePath, "SingleTargetLexRefs"); // This test checks that LexReference objects with less than two Targets are identified and removed // and that an error message is produced for them. string lexRefDeleteGuid1 = "d4bea1a5-9877-4f16-bd56-9bb7ff6b2db1"; string lexRefDeleteGuid2 = "1ad0d051-b388-45e1-a45e-48cb4274df90"; string lexRefNotDeleted = "580dc185-b017-4d83-b302-8179538be3a1"; string lexRefTypeChangedGuid = "0d5692fa-aa84-4bed-ab0a-f05186315fcd"; var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); // Should be two errors reported Assert.AreEqual(2, _errors.Count, "Unexpected number of errors found."); Assert.True(_errors[0].StartsWith("Removing LexReference with too few references (Targets) (guid='" + lexRefDeleteGuid1 + "') from its owner (guid='" + lexRefTypeChangedGuid), "Error message is incorrect."); // SequenceFixer--ksRemovingBadLexReference Assert.True(_errors[1].StartsWith("Removing LexReference with too few references (Targets) (guid='" + lexRefDeleteGuid2 + "') from its owner (guid='" + lexRefTypeChangedGuid), "Error message is incorrect."); // SequenceFixer--ksRemovingBadLexReference // Check original errors AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexReference\"]", 3, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + lexRefDeleteGuid1 + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + lexRefDeleteGuid2 + "\"]", 1, false); // Check that they were fixed // Should have deleted both LexReference objects AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + lexRefDeleteGuid1 + "\"]", 0, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + lexRefDeleteGuid2 + "\"]", 0, false); // Should still have the LexRefType object AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexRefType\" and @guid=\"" + lexRefTypeChangedGuid + "\"]", 1, false); // And that it has only one objsur now AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//objsur[@guid=\"" + lexRefNotDeleted + "\"]", 1, false); // Check that the valid LexReference is not deleted AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"LexReference\"]", 1, false); }
/// <summary> /// Make any required fixes to the MSA child element. /// </summary> /// <param name="rt"></param> /// <param name="logger"></param> /// <param name="guidString"></param> private void FixMsa(XElement rt, FwDataFixer.ErrorLogger logger, string guidString) { var destGuidString = ChildSurrogateGuid(rt, "Msa"); if (destGuidString == null) return; var objsur = rt.Element("Msa").Element("objsur"); // parts of path must exist, we got destGuidString if (m_guids.Contains(new Guid(destGuidString)) && !m_senseFixer.IsRejectedMsa(objsur)) return; // msa is not dangling. var senseGuid = ChildSurrogateGuid(rt, "Sense"); string senseMsaGuid; if (senseGuid != null && m_senseToMsa.TryGetValue(senseGuid, out senseMsaGuid) && m_guids.Contains(new Guid(senseMsaGuid))) { // We can repair it to match the sense's msa, an ideal repair, since we checked the sense's msa IS valid. objsur.SetAttributeValue("guid", senseMsaGuid); logger(guidString, DateTime.Now.ToShortDateString(), String.Format(Strings.ksRepairingMorphBundleFromSense, guidString)); return; } // Next see if we can link to a unique msa via our morph child. var morphGuidString = ChildSurrogateGuid(rt, "Morph"); Guid entryGuid; XElement entryElt; if (morphGuidString != null && m_owners.TryGetValue(new Guid(morphGuidString), out entryGuid) && m_entrys.TryGetValue(entryGuid.ToString(), out entryElt)) { var soleEntryMsa = GetSoleMsaGuid(entryElt); if (soleEntryMsa != null) { objsur.SetAttributeValue("guid", soleEntryMsa); logger(guidString, DateTime.Now.ToShortDateString(), String.Format(Strings.ksRepairingMorphBundleFromEntry, guidString)); return; } } // If we can't fix it nicely, just clobber it (and its parent, since this is an atomic property). logger(guidString, DateTime.Now.ToShortDateString(), String.Format(Strings.ksRemovingDanglingMsa, destGuidString, guidString)); objsur.Parent.Remove(); }
//Go through the list of MSA references in the file and remove those which do not occur in any sense //Why? Because the Chorus merge will flag a conflict for the users but end up placing both references //in the entry. This incorrectly causes parts of speech to be referenced in the Entry which no sense uses. internal override bool FixElement(XElement rt, FwDataFixer.ErrorLogger logger) { var guid = rt.Attribute("guid"); if (guid == null) return true; if (rt.Attribute("class").Value == "LexEntry") { var MSAs = rt.Element("MorphoSyntaxAnalyses"); var rejects = new List<XNode>(); if (MSAs != null) { var entryGuidString = guid.Value; foreach (var objsur in MSAs.Descendants("objsur")) { if (IsRejectedMsa(objsur)) { rejects.Add(objsur); } } foreach (var reject in rejects) { logger(entryGuidString, DateTime.Now.ToShortDateString(), Strings.ksRemovedUnusedMsa); reject.Remove(); } } } return true; }
public void TestDanglingWordformLinks() { var testPath = Path.Combine(basePath, "MorphBundleProblems"); var data = new FwDataFixer(Path.Combine(testPath, "BasicFixup.fwdata"), new DummyProgressDlg(), LogErrors, ErrorCount); data.FixErrorsAndSave(); var danglingMsaGuid = "aaaaaaaa-e15a-448e-a618-3855f93bd3c2"; // nonexistent 'msa' var repairableBundleGuid = "10f3db1e-33db-4d9d-9a06-e0a8e1ed8a92"; var unrepairableBundleGuid = "d70b57bc-ecfe-4e32-a590-f2852bce69fc"; var repairOnlyMsaBundleGuid = "e4396e8e-b7d2-43ba-93bd-104cf2011aaf"; var repairForWillDeleteMsa = "cb941dc9-6f6e-44b2-97f2-07854e164b4e"; var willDeleteMsaGuid = "63d132a9-4a41-43bb-a395-a6ad7f3ae7e2"; var danglingMorphGoodSenseGuid = "9665bf3b-2aab-4f7f-88a9-4ca738b75110"; var danglingMorphNoRepairGuid = "5752ed24-40e1-4282-9ba0-d82c89592432"; var danglingMorphNoRepairAfGuid = "1f568cae-b0f8-413d-84a6-41cbd90923e9"; // Verify initial state. // We start out with morph bundles that have broken links. AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + repairableBundleGuid + "\"]/Msa/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + unrepairableBundleGuid + "\"]/Msa/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + repairOnlyMsaBundleGuid + "\"]/Msa/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); // This one is not obviously broken, but the grammatical sense fixer will kill its target. AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + repairForWillDeleteMsa + "\"]/Msa/objsur[@guid=\"" + willDeleteMsaGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"MoStemMsa\" and @guid=\"" + willDeleteMsaGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + danglingMorphGoodSenseGuid + "\"]/Morph/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + danglingMorphNoRepairGuid + "\"]/Morph/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.bak")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + danglingMorphNoRepairAfGuid + "\"]/Morph/objsur[@guid=\"" + danglingMsaGuid + "\"]", 1, false); // Check errors Assert.AreEqual(10, _errors.Count, "Unexpected number of errors found."); Assert.True(_errors[0].StartsWith("Removing dangling link to '" + danglingMsaGuid + "' (class='LexEntry'"), "Error message is incorrect."); // OriginalFixer--ksRemovingLinkToNonexistingObject Assert.That(_errors[1], Is.EqualTo("Fixing link to MSA based on Sense MSA (class='WfiMorphBundle', guid='" + repairableBundleGuid + "')."), "Error message is incorrect."); // MorphBundleFixer--ksRepairingMorphBundleFromSense Assert.That(_errors[2], Is.EqualTo("Removing dangling link to MSA '" + danglingMsaGuid + "' for WfiMorphBundle '" + unrepairableBundleGuid + "'."), "Error message is incorrect."); // MorphBundleFixer--ksRemovingDanglingMsa Assert.That(_errors[3], Is.EqualTo("Fixing link to MSA based on only MSA of entry for WfiMorphBundle '" + repairOnlyMsaBundleGuid + "'."), "Error message is incorrect."); // MorphBundleFixer--ksRepairingMorphBundleFromEntry // 4 is removing the unused MSA reference. Not interesting here. // 5 is removing the unused rt MSA element. Not interesting here. Assert.That(_errors[6], Is.EqualTo("Fixing link to MSA based on only MSA of entry for WfiMorphBundle '" + repairForWillDeleteMsa + "'."), "Error message is incorrect."); // MorphBundleFixer--ksRepairingMorphBundleFromEntry Assert.That(_errors[7], Is.EqualTo("Fixing link to Form based on only Form of entry for WfiMorphBundle '" + danglingMorphGoodSenseGuid + "'."), "Error message is incorrect."); // MorphBundleFixer--ksRemovingDanglingMsa Assert.That(_errors[8], Is.EqualTo("Removing dangling link to Form '" + danglingMsaGuid + "' for WfiMorphBundle '" + danglingMorphNoRepairGuid + "'."), "Error message is incorrect."); // MorphBundleFixer--ksRemovingDanglingMorph Assert.That(_errors[9], Is.EqualTo("Removing dangling link to Form '" + danglingMsaGuid + "' for WfiMorphBundle '" + danglingMorphNoRepairAfGuid + "'."), "Error message is incorrect."); // MorphBundleFixer--ksRemovingDanglingMorph // Check file repair AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + repairableBundleGuid + "\"]/Msa/objsur[@guid=\"408ba7ca-e15a-448e-a618-3855f93bd3c2\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + unrepairableBundleGuid + "\"]/Msa", 0, false); // must remove Msa, not just child objsur AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + repairOnlyMsaBundleGuid + "\"]/Msa/objsur[@guid=\"408ba7ca-e15a-448e-a618-3855f93bd3c2\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + repairForWillDeleteMsa + "\"]/Msa/objsur[@guid=\"26ae3989-d424-4dd2-a32d-c556c6985a99\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + danglingMorphGoodSenseGuid + "\"]/Morph/objsur[@guid=\"8056c7d9-70ea-41b9-89e9-de28f7d686a7\"]", 1, false); AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + danglingMorphNoRepairGuid + "\"]/Morph", 0, false); // must remove Morph, not just child objsur AssertThatXmlIn.File(Path.Combine(testPath, "BasicFixup.fwdata")).HasSpecifiedNumberOfMatchesForXpath( "//rt[@class=\"WfiMorphBundle\" and @guid=\"" + danglingMorphNoRepairAfGuid + "\"]/Morph/objsur", 0, false); }