// Copyright (C) Stichting Deltares 2016. All rights reserved.
//
// This file is part of Ringtoets.
//
// Ringtoets is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Linq;
using Core.Common.TestUtil;
using NUnit.Framework;
using Rhino.Mocks;
namespace Core.Common.Base.Test
{
[TestFixture]
public class ObservableUniqueItemCollectionWithSourcePathTest
{
private readonly Func getUniqueFeature = (item => item.Name);
private const string typeDescriptor = "TestItems";
private const string featureDescription = "Feature";
[Test]
public void DefaultConstructor_getUniqueFeatureNull_ThrowsArgumentNullException()
{
// Call
TestDelegate call = () => new ObservableUniqueItemCollectionWithSourcePath(
null, string.Empty, string.Empty);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("getUniqueFeature", paramName);
}
[Test]
public void DefaultConstructor_TypeDescriptionNull_ThrowsArgumentNullException()
{
// Call
TestDelegate call = () => new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, null, string.Empty);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("typeDescriptor", paramName);
}
[Test]
public void DefaultConstructor_FeatureDescriptionNull_ThrowsArgumentNullException()
{
// Call
TestDelegate call = () => new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, string.Empty, null);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("featureDescription", paramName);
}
[Test]
public void DefaultConstructor_ReturnObservableUniqueItemCollectionWithSourcePath()
{
// Call
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
// Assert
Assert.IsInstanceOf(collection);
Assert.IsNull(collection.SourcePath);
Assert.AreEqual(0, collection.Count);
CollectionAssert.IsEmpty(collection);
}
[Test]
public void AddRange_ItemsNull_ThrowArgumentNullException()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
// Call
TestDelegate call = () => collection.AddRange(null, "path");
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("items", paramName);
}
[Test]
public void AddRange_ItemsHasNullElement_ThrowArgumentException()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
var items = new[]
{
new TestItem("Item A"),
null,
new TestItem("Item B")
};
// Call
TestDelegate call = () => collection.AddRange(items, "path");
// Assert
string message = "Collection cannot contain null.";
string paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, message).ParamName;
Assert.AreEqual("items", paramName);
}
[Test]
public void AddRange_FilePathNull_ThrowArgumentNullException()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
// Call
TestDelegate call = () => collection.AddRange(Enumerable.Empty(), null);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("filePath", paramName);
}
[Test]
public void AddRange_NotAnActualFilePath_ThrowArgumentNull()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
const string invalidFilePath = @" ";
// Call
TestDelegate call = () => collection.AddRange(Enumerable.Empty(), invalidFilePath);
// Assert
string message = $"'{invalidFilePath}' is not a valid filepath.";
string paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, message).ParamName;
Assert.AreEqual("filePath", paramName);
}
[Test]
public void AddRange_AddNewItem_CollectionContainsItem()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
var item = new TestItem("Item A");
// Call
const string filePath = "some/file/path";
collection.AddRange(new[]
{
item
}, filePath);
// Assert
CollectionAssert.Contains(collection, item);
Assert.AreEqual(filePath, collection.SourcePath);
}
[Test]
public void AddRange_AddingNewItems_CollectionContainsExpectedElements()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
var expectedCollection = new[]
{
new TestItem("Item A"),
new TestItem("Item B"),
new TestItem("Item C"),
new TestItem("Item D")
};
const string filePath = "some/file/path";
// Call
collection.AddRange(expectedCollection, filePath);
// Assert
CollectionAssert.AreEqual(expectedCollection, collection);
Assert.AreEqual(filePath, collection.SourcePath);
}
[Test]
public void AddRange_AddDuplicateItems_ThrowsArgumentException()
{
// Setup
const string duplicateNameOne = "Duplicate name it is";
var itemsToAdd = new[]
{
new TestItem(duplicateNameOne),
new TestItem(duplicateNameOne)
};
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
// Call
TestDelegate call = () => collection.AddRange(itemsToAdd, "some/path");
// Assert
string message = $"{typeDescriptor} moeten een unieke {featureDescription} hebben. Gevonden dubbele elementen: {duplicateNameOne}.";
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, message);
}
[Test]
public void AddRange_AddMultipleDuplicateItems_ThrowsArgumentException()
{
// Setup
const string duplicateNameOne = "Duplicate name it is";
const string duplicateNameTwo = "Duplicate name again";
var itemsToAdd = new[]
{
new TestItem(duplicateNameOne),
new TestItem(duplicateNameOne),
new TestItem(duplicateNameTwo),
new TestItem(duplicateNameTwo)
};
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
// Call
TestDelegate call = () => collection.AddRange(itemsToAdd, "some/path");
// Assert
string message = $"{typeDescriptor} moeten een unieke {featureDescription} hebben. Gevonden dubbele elementen: {duplicateNameOne}, {duplicateNameTwo}.";
TestHelper.AssertThrowsArgumentExceptionAndTestMessage(call, message);
}
[Test]
public void Count_CollectionFilledWithElements_ReturnsExpectedNumberOfElements()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
collection.AddRange(new[]
{
new TestItem("Item A"),
new TestItem("Item B"),
new TestItem("Item C"),
new TestItem("Item D")
}, "path");
// Call
int nrOfElements = collection.Count;
// Assert
Assert.AreEqual(4, nrOfElements);
}
[Test]
[TestCase(-1)]
[TestCase(0)]
public void Indexer_GetItemAtIndexOutOfRange_ThrowsArgumentOutOfRangeException(int invalidIndex)
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
// Call
TestDelegate call = () =>
{
object item = collection[invalidIndex];
};
// Assert
Assert.Throws(call);
}
[Test]
public void Indexer_GetElementAtIndex_ReturnsExpectedElement()
{
// Setup
var elementToRetrieve = new TestItem("Item X");
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
collection.AddRange(new[]
{
new TestItem("Item A"),
new TestItem("Item B"),
new TestItem("Item C"),
new TestItem("Item D"),
elementToRetrieve
}, "path");
// Call
object retrievedElement = collection[4];
// Assert
Assert.AreSame(elementToRetrieve, retrievedElement);
}
[Test]
public void Remove_ElementNotInList_ReturnsFalse()
{
// Setup
var element = new TestItem("Item X");
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
var expectedCollection = new[]
{
new TestItem("Item A"),
new TestItem("Item B"),
new TestItem("Item C"),
new TestItem("Item D")
};
collection.AddRange(expectedCollection, "path");
// Call
bool removeSuccessful = collection.Remove(element);
// Assert
Assert.IsFalse(removeSuccessful);
CollectionAssert.AreEqual(expectedCollection, collection);
}
[Test]
public void Remove_ElementInCollection_ReturnsTrue()
{
// Setup
var elementToBeRemoved = new TestItem("Item X");
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
var expectedCollections = new[]
{
new TestItem("Item A"),
new TestItem("Item B"),
new TestItem("Item C"),
new TestItem("Item D")
};
collection.AddRange(expectedCollections.Concat(new[]
{
elementToBeRemoved
}), "path");
// Call
bool removeSuccessful = collection.Remove(elementToBeRemoved);
// Assert
Assert.IsTrue(removeSuccessful);
CollectionAssert.AreEqual(expectedCollections, collection);
}
[Test]
public void Remove_RemoveLastElement_ReturnsTrueAndClearSourcePath()
{
// Setup
var elementToBeRemoved = new TestItem("Item X");
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
collection.AddRange(new[]
{
elementToBeRemoved
}, "path");
// Precondition
Assert.IsNotNull(collection.SourcePath);
// Call
bool removeSuccesful = collection.Remove(elementToBeRemoved);
// Assert
Assert.IsTrue(removeSuccesful);
Assert.IsNull(collection.SourcePath);
}
[Test]
public void Clear_CollectionFullyDefined_ClearsSourcePathAndCollection()
{
// Setup
var collection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
var expectedObjectCollection = new[]
{
new TestItem("Item A"),
new TestItem("Item B"),
new TestItem("Item C"),
new TestItem("Item D")
};
collection.AddRange(expectedObjectCollection, "path");
// Call
collection.Clear();
// Assert
Assert.IsNull(collection.SourcePath);
Assert.AreEqual(0, collection.Count);
CollectionAssert.IsEmpty(collection);
}
[Test]
public void NotifyObservers_WithObserverAttached_ObserverIsNotified()
{
// Setup
var mocks = new MockRepository();
var observer = mocks.StrictMock();
observer.Expect(o => o.UpdateObserver()); // Expect to be called once
mocks.ReplayAll();
var observableCollection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
observableCollection.Attach(observer);
// Call
observableCollection.NotifyObservers();
// Assert
mocks.VerifyAll();
}
[Test]
public void NotifyObserver_AttachedObserverDetachedAgain_ObserverNoLongerNotified()
{
// Setup
var mocks = new MockRepository();
var observer = mocks.StrictMock();
mocks.ReplayAll();
var observableCollection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
observableCollection.Attach(observer);
observableCollection.Detach(observer);
// Call
observableCollection.NotifyObservers();
// Assert
mocks.VerifyAll(); // Expect no calls on 'observer'
}
[Test]
public void NotifyObservers_MultipleObserversDetachingOrAttachingOthers_NoUpdatesForAttachedAndDetachedObservers()
{
// Setup
var mocks = new MockRepository();
var observableCollection = new ObservableUniqueItemCollectionWithSourcePath(
getUniqueFeature, typeDescriptor, featureDescription);
var observer1 = mocks.Stub();
var observer2 = mocks.Stub();
var observer3 = mocks.Stub();
var observer4 = mocks.Stub();
var observer5 = mocks.Stub();
var observer6 = mocks.Stub();
observableCollection.Attach(observer1);
observableCollection.Attach(observer2);
observableCollection.Attach(observer3);
observableCollection.Attach(observer4);
observableCollection.Attach(observer6);
observer1.Expect(o => o.UpdateObserver());
observer2.Expect(o => o.UpdateObserver()).Do((Action) (() => observableCollection.Detach(observer3)));
observer3.Expect(o => o.UpdateObserver()).Repeat.Never(); // A detached observer should no longer be updated
observer4.Expect(o => o.UpdateObserver()).Do((Action) (() => observableCollection.Attach(observer5)));
observer5.Expect(o => o.UpdateObserver()).Repeat.Never(); // An attached observer should not be updated too
observer6.Expect(o => o.UpdateObserver());
mocks.ReplayAll();
// Call
observableCollection.NotifyObservers();
// Assert
mocks.VerifyAll();
}
private class TestItem
{
public string Name { get; }
public TestItem(string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
}
}
}