public void ServiceThrowsOnRemoveTermWithoutName() { var service = new XmlTermsService(String.Empty); // Test null. try { service.RemoveTerm(new Term(null, String.Empty), Scheduler.Immediate); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(ArgumentException)); Assert.IsTrue(((ArgumentException)ex).ParamName == "term"); } // Test whitespace. try { service.RemoveTerm(new Term(" ", String.Empty), Scheduler.Immediate); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(ArgumentException)); Assert.IsTrue(((ArgumentException)ex).ParamName == "term"); } }
/// <summary> /// Gets an observable that removes an existing term from the storage. /// </summary> /// <param name="term">A term to remove from the storage.</param> /// <param name="scheduler">A scheduler to invoke service operations on.</param> /// <returns>An observable sequence that removes the specified term and pushes /// it to subscribers.</returns> public IObservable <Term> RemoveTerm(Term term, IScheduler scheduler) { XmlTermsService.ApplyTermRules(term, "term"); return(Observable .Return(term, scheduler) .Do(_ => { var doc = this.LoadStorage(); // Search for a node to remove. var xTerm = doc .Descendants(TermXmlNames.TermElement) .SingleOrDefault(el => el.Attribute(TermXmlNames.TermNameAttribute).Value == term.Name); if (xTerm == null) { throw new InvalidOperationException(String.Format( Resources.UnableToRemoveNonExistentTerm, term.Name)); } xTerm.Remove(); this.SaveStorage(doc); })); }
public void ServiceThrowsOnUpdateNullTerm() { // Check validation of old term. var service = new XmlTermsService(String.Empty); try { service.UpdateTerm(null, XmlTermsServiceFixture.SampleTerms[0], Scheduler.Immediate); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(ArgumentNullException)); Assert.IsTrue(((ArgumentNullException)ex).ParamName == "oldTerm"); } // Check validation of new term. service = new XmlTermsService(String.Empty); try { service.UpdateTerm(XmlTermsServiceFixture.SampleTerms[0], null, Scheduler.Immediate); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(ArgumentNullException)); Assert.IsTrue(((ArgumentNullException)ex).ParamName == "newTerm"); } }
public void ServiceThrowsOnUpdateToTermWithoutName() { var service = new XmlTermsService(String.Empty); var nameless = new Term(null, String.Empty); var whitespace = new Term(" ", String.Empty); // Test null. try { service.UpdateTerm(XmlTermsServiceFixture.SampleTerms[0], nameless, Scheduler.Immediate); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(ArgumentException)); Assert.IsTrue(((ArgumentException)ex).ParamName == "newTerm"); } // Test whitespace. try { service.UpdateTerm(XmlTermsServiceFixture.SampleTerms[0], whitespace, Scheduler.Immediate); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(ArgumentException)); Assert.IsTrue(((ArgumentException)ex).ParamName == "newTerm"); } }
public void ObservableUpdatesAndPushesTerm() { var fileName = XmlTermsServiceFixture.TermsToFile( XmlTermsServiceFixture.SampleTerms, "ObservableUpdatesAndPushesTerm.xml"); var service = new XmlTermsService(fileName); var oldTerm = XmlTermsServiceFixture.SampleTerms[0]; var newTerm = new Term("new term0", "new def 0"); Term pushed = null; service .UpdateTerm(oldTerm, newTerm, Scheduler.Immediate) .Subscribe(p => pushed = p); Assert.AreEqual(newTerm, pushed); // Check that old term is deleted. var xTerm = XDocument.Load(fileName) .Descendants(TermXmlNames.TermElement) .FirstOrDefault(x => x.Attribute(TermXmlNames.TermNameAttribute).Value == oldTerm.Name); Assert.IsNull(xTerm); // Check that new term is added. xTerm = XDocument.Load(fileName) .Descendants(TermXmlNames.TermElement) .FirstOrDefault(x => x.Attribute(TermXmlNames.TermNameAttribute).Value == newTerm.Name); Assert.IsNotNull(xTerm); Assert.AreEqual(newTerm.Definition, xTerm.Attribute(TermXmlNames.TermDefinitionAttribute).Value); }
/// <summary> /// Gets an observable that adds a new term to the storage. /// </summary> /// <param name="term">A term to add to the storage.</param> /// <param name="scheduler">A scheduler to invoke service operations on.</param> /// <returns>An observable sequence that adds the specified term and pushes /// it to subscribers.</returns> public IObservable <Term> AddTerm(Term term, IScheduler scheduler) { XmlTermsService.ApplyTermRules(term, "term"); return(Observable .Return(term, scheduler) .Do(_ => { var doc = this.LoadStorage(); // Check whether a term with the same name already exists. // A client must use UpdateTerm in this case. if (doc .Descendants(TermXmlNames.TermElement) .Any(el => el.Attribute(TermXmlNames.TermNameAttribute).Value == term.Name)) { throw new InvalidOperationException(String.Format( Resources.UnableToAddTermAlreadyExists, term.Name)); } var xTerm = new XElement( TermXmlNames.TermElement, new XAttribute(TermXmlNames.TermNameAttribute, term.Name)); if (!String.IsNullOrEmpty(term.Definition)) { xTerm.Add(new XAttribute(TermXmlNames.TermDefinitionAttribute, term.Definition)); } doc.Root.Add(xTerm); this.SaveStorage(doc); })); }
public void ObservableThrowsWhenFileDoesntExist() { var service = new XmlTermsService(String.Empty); ReactiveAssert.Throws <InvalidTermsStorageException>( () => { service .LoadTerms(Scheduler.Immediate) .Subscribe(); }); }
/// <summary> /// Gets an observable that updates an existing term in the storage. /// </summary> /// <param name="oldTerm">An old value of term to update in the storage.</param> /// <param name="newTerm">A new value of term.</param> /// <param name="scheduler">A scheduler to invoke service operations on.</param> /// <returns>An observable sequence that updates the specified term and pushes /// it to subscribers.</returns> public IObservable <Term> UpdateTerm(Term oldTerm, Term newTerm, IScheduler scheduler) { XmlTermsService.ApplyTermRules(oldTerm, "oldTerm"); XmlTermsService.ApplyTermRules(newTerm, "newTerm"); return(Observable .Return(newTerm, scheduler) .Do(_ => { var doc = this.LoadStorage(); // Check whether an old term already exists. // If it is not, the client must use AddTerm. var xTerm = doc .Descendants(TermXmlNames.TermElement) .SingleOrDefault(el => el.Attribute(TermXmlNames.TermNameAttribute).Value == oldTerm.Name); if (xTerm == null) { throw new InvalidOperationException(String.Format( Resources.UnableToUpdateNonExistentTerm, oldTerm.Name)); } // Check whether a new term already exists if names are different. if (oldTerm.Name != newTerm.Name) { var newTermExists = doc .Descendants(TermXmlNames.TermElement) .Any(el => el.Attribute(TermXmlNames.TermNameAttribute).Value == newTerm.Name); if (newTermExists) { throw new InvalidOperationException(String.Format( Resources.UnableToUpdateToAnotherExistentTerm, newTerm.Name)); } } xTerm.Attribute(TermXmlNames.TermNameAttribute).Value = newTerm.Name; if (!String.IsNullOrEmpty(newTerm.Definition)) { xTerm.SetAttributeValue(TermXmlNames.TermDefinitionAttribute, newTerm.Definition); } else { xTerm.Attribute(TermXmlNames.TermDefinitionAttribute).Remove(); } this.SaveStorage(doc); })); }
public void ObservableLoadsNoTermsFromEmptyValidXml() { var service = new XmlTermsService(XmlTermsServiceFixture.TermsToFile( Enumerable.Empty <Term>(), "ObservableLoadsNoTermsFromEmptyValidXml.xml")); var serviceTerms = new List <Term>(); service .LoadTerms(Scheduler.Immediate) .Subscribe(terms => serviceTerms.AddRange(terms)); ReactiveAssert.AreElementsEqual(Enumerable.Empty <Term>(), serviceTerms); }
public void ServiceThrowsOnRecreateNothing() { var service = new XmlTermsService(String.Empty); try { service.RecreateStorage(null, Scheduler.Immediate); Assert.Fail(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(ArgumentNullException)); Assert.IsTrue(((ArgumentNullException)ex).ParamName == "terms"); } }
public void ObservableThrowsOnAddExistingTerm() { var service = new XmlTermsService(XmlTermsServiceFixture.TermsToFile( XmlTermsServiceFixture.SampleTerms, "ObservableThrowsOnAddExistingTerm.xml")); Exception ex = null; service .AddTerm(XmlTermsServiceFixture.SampleTerms[0], Scheduler.Immediate) .Subscribe(_ => { }, ex2 => ex = ex2, () => { }); Assert.IsInstanceOfType(ex, typeof(InvalidOperationException)); Assert.IsTrue(ex.Message.Contains("already exists")); }
/// <summary> /// Gets an observable sequence that retrieves terms from the storage. /// </summary> /// <param name="scheduler">A scheduler to invoke service operations on.</param> /// <returns>An observable sequence of portions of terms.</returns> public IObservable <IEnumerable <Term> > LoadTerms(IScheduler scheduler) { return(Observable .Return(Unit.Default, scheduler) .SelectMany(_ => this.LoadStorage().Descendants(TermXmlNames.TermElement)) .Select(node => new Term( node.Attribute(TermXmlNames.TermNameAttribute).Value, node.Attribute(TermXmlNames.TermDefinitionAttribute).Value)) .Do(term => XmlTermsService.ApplyTermRules(term, "term")) .Catch((Exception ex) => Observable.Throw <Term>( XmlTermsService.WrapIntoInvalidStorageException( ex, String.Format(Resources.InvalidXmlStorageToLoad, this._fileName)))) .ToArray()); }
public void ObservableThrowsOnRemoveNonExistentTerm() { var service = new XmlTermsService(XmlTermsServiceFixture.TermsToFile( XmlTermsServiceFixture.SampleTerms, "ObservableThrowsOnRemoveNonExistentTerm.xml")); var newTerm = new Term("nonExistentTerm", String.Empty); Exception ex = null; service .RemoveTerm(newTerm, Scheduler.Immediate) .Subscribe(_ => { }, ex2 => ex = ex2, () => { }); Assert.IsInstanceOfType(ex, typeof(InvalidOperationException)); Assert.IsTrue(ex.Message.Contains("doesn't exist")); }
public void ObservableRecreatesNewStorage() { var filePath = Path.Combine(XmlTermsServiceFixture.DeploymentDirectory, "ObservableRecreatesNewStorage.xml"); var service = new XmlTermsService(filePath); service .RecreateStorage(XmlTermsServiceFixture.SampleTerms, Scheduler.Immediate) .Subscribe(); var storedTerms = new List <Term>(); service .LoadTerms(Scheduler.Immediate) .Subscribe(terms => storedTerms.AddRange(terms)); ReactiveAssert.AreElementsEqual(XmlTermsServiceFixture.SampleTerms, storedTerms); }
public void ObservableThrowsFromInvalidXml() { var service = new XmlTermsService(XmlTermsServiceFixture.TermsToFile( new Term[] { XmlTermsServiceFixture.SampleTerms[0], new Term(null, String.Empty), }, "ObservableThrowsFromInvalidXml.xml")); ReactiveAssert.Throws <InvalidTermsStorageException>( () => { service .LoadTerms(Scheduler.Immediate) .Subscribe(); }); }
public void ObservableShouldntPushTermsFromInvalidXml() { var mix = new Term[] { XmlTermsServiceFixture.SampleTerms[0], new Term(null, null), XmlTermsServiceFixture.SampleTerms[1], }; var service = new XmlTermsService( XmlTermsServiceFixture.TermsToFile(mix, "ObservableShouldntPushTermsFromInvalidXml.xml")); bool onNextInvoked = false; service .LoadTerms(Scheduler.Immediate) .Subscribe(terms => onNextInvoked = true, _ => { }, () => { }); Assert.IsFalse(onNextInvoked); }
public void ObservableAddsAndPushesNewTerm() { var fileName = XmlTermsServiceFixture.TermsToFile( XmlTermsServiceFixture.SampleTerms, "ObservableAddsAndPushesNewTerm.xml"); var service = new XmlTermsService(fileName); var term = new Term("newTerm", "newDef"); Term pushed = null; service.AddTerm(term, Scheduler.Immediate).Subscribe(p => pushed = p); Assert.AreEqual(term, pushed); var xTerm = XDocument.Load(fileName) .Descendants(TermXmlNames.TermElement) .FirstOrDefault(x => x.Attribute(TermXmlNames.TermNameAttribute).Value.Equals(term.Name)); Assert.IsNotNull(xTerm); Assert.AreEqual(term.Definition, xTerm.Attribute(TermXmlNames.TermDefinitionAttribute).Value); }
public void ObservableRemovesAndPushesTerm() { var fileName = XmlTermsServiceFixture.TermsToFile( XmlTermsServiceFixture.SampleTerms, "ObservableRemovesTerm.xml"); var service = new XmlTermsService(fileName); var term = XmlTermsServiceFixture.SampleTerms[0]; Term pushed = null; service .RemoveTerm(term, Scheduler.Immediate) .Subscribe(p => pushed = p); Assert.AreEqual(term, pushed); var xTerm = XDocument.Load(fileName) .Descendants(TermXmlNames.TermElement) .FirstOrDefault(x => x.Attribute(TermXmlNames.TermNameAttribute).Value == term.Name); Assert.IsNull(xTerm); }
/// <summary> /// Gets an observable that recreates storage with the specified terms. /// </summary> /// <param name="terms">A terms to add to a new storage.</param> /// <param name="scheduler">A scheduler to invoke service operations on.</param> /// <returns>An observable sequence that recreates storage.</returns> public IObservable <Unit> RecreateStorage(IEnumerable <Term> terms, IScheduler scheduler) { if (terms == null) { throw new ArgumentNullException("terms"); } return(Observable .Return(Unit.Default, scheduler) .Do(_ => { var doc = new XDocument(new XElement(TermXmlNames.TermsElement)); foreach (var term in terms) { XmlTermsService.ApplyTermRules(term, "terms"); var xTerm = new XElement( TermXmlNames.TermElement, new XAttribute(TermXmlNames.TermNameAttribute, term.Name)); if (!String.IsNullOrEmpty(term.Definition)) { xTerm.Add(new XAttribute(TermXmlNames.TermDefinitionAttribute, term.Definition)); } doc.Root.Add(xTerm); } this.SaveStorage(doc); }) .Catch((Exception ex) => Observable.Throw <Unit>( XmlTermsService.WrapIntoInvalidStorageException( ex, String.Format(Resources.InvalidXmlStorageToSave, this._fileName))))); }
public void ObservableThrowsOnRecreateInvalidTerms() { var service = new XmlTermsService(String.Empty); // Test null. var invalidTerms = new Term[] { XmlTermsServiceFixture.SampleTerms[0], new Term(null, String.Empty), }; Exception ex = null; service .RecreateStorage(invalidTerms, Scheduler.Immediate) .Subscribe(_ => { }, ex2 => ex = ex2, () => { }); Assert.IsInstanceOfType(ex, typeof(InvalidTermsStorageException)); // Test whitespace. invalidTerms = new Term[] { XmlTermsServiceFixture.SampleTerms[0], new Term(" ", String.Empty), }; ex = null; service .RecreateStorage(invalidTerms, Scheduler.Immediate) .Subscribe(_ => { }, ex2 => ex = ex2, () => { }); Assert.IsInstanceOfType(ex, typeof(InvalidTermsStorageException)); }