// Copyright (C) Stichting Deltares 2017. 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 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 General Public License for more details. // // You should have received a copy of the GNU 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.Globalization; using Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Base.Geometry; using Core.Common.Controls.DataGrid; using Core.Common.TestUtil; using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.TestUtil; using Ringtoets.Common.Forms.PresentationObjects; using Ringtoets.Common.Forms.PropertyClasses; using Ringtoets.Common.Forms.TestUtil; using Ringtoets.Piping.Data; using Ringtoets.Piping.Data.SoilProfile; using Ringtoets.Piping.Data.TestUtil; using Ringtoets.Piping.Forms.Views; using Ringtoets.Piping.Primitives.TestUtil; namespace Ringtoets.Piping.Forms.Test.Views { [TestFixture] public class PipingCalculationRowTest { [Test] public void Constructor_WithoutPipingCalculation_ThrowsArgumentNullException() { // Setup var mocks = new MockRepository(); var handler = mocks.Stub(); mocks.ReplayAll(); // Call TestDelegate test = () => new PipingCalculationRow(null, handler); // Assert string paramName = Assert.Throws(test).ParamName; Assert.AreEqual("pipingCalculation", paramName); mocks.VerifyAll(); } [Test] public void Constructor_WithoutHandler_ThrowsArgumentNullException() { // Call TestDelegate test = () => new PipingCalculationRow(new PipingCalculationScenario(new GeneralPipingInput()), null); // Assert string paramName = Assert.Throws(test).ParamName; Assert.AreEqual("handler", paramName); } [Test] public void Constructor_WithPipingCalculation_PropertiesFromPipingCalculation() { // Setup var mocks = new MockRepository(); var handler = mocks.Stub(); mocks.ReplayAll(); var hydraulicBoundaryLocation = new TestHydraulicBoundaryLocation(); PipingCalculationScenario calculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithValidInput(hydraulicBoundaryLocation); // Call var row = new PipingCalculationRow(calculation, handler); // Assert Assert.AreSame(calculation, row.PipingCalculation); Assert.AreEqual(calculation.Name, row.Name); Assert.AreSame(calculation.InputParameters.StochasticSoilModel, row.StochasticSoilModel.WrappedObject); Assert.AreSame(calculation.InputParameters.StochasticSoilProfile, row.StochasticSoilProfile.WrappedObject); Assert.AreEqual(calculation.InputParameters.StochasticSoilProfile.Probability.ToString(CultureInfo.CurrentCulture), row.StochasticSoilProfileProbability); Assert.AreSame(hydraulicBoundaryLocation, row.SelectableHydraulicBoundaryLocation.WrappedObject.HydraulicBoundaryLocation); Assert.AreEqual(calculation.InputParameters.DampingFactorExit.Mean, row.DampingFactorExitMean); Assert.AreEqual(calculation.InputParameters.PhreaticLevelExit.Mean, row.PhreaticLevelExitMean); Assert.AreEqual(calculation.InputParameters.EntryPointL, row.EntryPointL); Assert.AreEqual(calculation.InputParameters.ExitPointL, row.ExitPointL); mocks.VerifyAll(); } [Test] public void Constructor_WithPipingCalculationWithInvalidInput_PropertiesFromPipingCalculation() { // Setup var mocks = new MockRepository(); var handler = mocks.Stub(); mocks.ReplayAll(); PipingCalculationScenario calculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithInvalidInput(); // Call var row = new PipingCalculationRow(calculation, handler); // Assert Assert.AreSame(calculation, row.PipingCalculation); Assert.IsNull(row.StochasticSoilModel.WrappedObject); Assert.IsNull(row.StochasticSoilProfile.WrappedObject); Assert.AreEqual("0", row.StochasticSoilProfileProbability); Assert.IsNull(row.SelectableHydraulicBoundaryLocation.WrappedObject); mocks.VerifyAll(); } [Test] public void Name_AlwaysOnChange_NotifyObserverAndCalculationPropertyChanged() { // Setup var mockRepository = new MockRepository(); var observer = mockRepository.StrictMock(); observer.Expect(o => o.UpdateObserver()); var handler = mockRepository.Stub(); mockRepository.ReplayAll(); const string newValue = "Test new name"; var calculation = new PipingCalculationScenario(new GeneralPipingInput()); var row = new PipingCalculationRow(calculation, handler); calculation.Attach(observer); // Call row.Name = newValue; // Assert Assert.AreEqual(newValue, calculation.Name); mockRepository.VerifyAll(); } [Test] public void StochasticSoilModel_AlwaysOnChange_NotifyObserverCalculationPropertyChangedOutputCleared() { // Setup PipingStochasticSoilModel newModel = PipingStochasticSoilModelTestFactory.CreatePipingStochasticSoilModel(); var newValue = new DataGridViewComboBoxItemWrapper(newModel); var calculation = new PipingCalculationScenario(new GeneralPipingInput()); // Call & Assert SetPropertyAndVerifyNotificationsAndOutputForCalculation(row => row.StochasticSoilModel = newValue, calculation); } [Test] public void StochasticSoilModel_ChangeToEqualValue_NoNotificationsOutputNotCleared() { // Setup DataGridViewComboBoxItemWrapper oldValue = null; // Call AssertPropertyNotChanged( row => { oldValue = row.StochasticSoilModel; row.StochasticSoilModel = row.StochasticSoilModel; }, calculation => { // Assert Assert.NotNull(oldValue); Assert.AreEqual(oldValue.WrappedObject, calculation.InputParameters.StochasticSoilModel); }); } [Test] public void StochasticSoilProfile_AlwaysOnChange_NotifyObserverAndCalculationPropertyChanged() { // Setup var newProfile = new PipingStochasticSoilProfile(0, PipingSoilProfileTestFactory.CreatePipingSoilProfile()); var newValue = new DataGridViewComboBoxItemWrapper(newProfile); var calculation = new PipingCalculationScenario(new GeneralPipingInput()); // Call & Assert SetPropertyAndVerifyNotificationsAndOutputForCalculation(row => row.StochasticSoilProfile = newValue, calculation); } [Test] public void StochasticSoilProfile_ChangeToEqualValue_NoNotificationsOutputNotCleared() { // Setup DataGridViewComboBoxItemWrapper oldValue = null; // Call AssertPropertyNotChanged( row => { oldValue = row.StochasticSoilProfile; row.StochasticSoilProfile = row.StochasticSoilProfile; }, calculation => { // Assert Assert.NotNull(oldValue); Assert.AreEqual(oldValue.WrappedObject, calculation.InputParameters.StochasticSoilProfile); }); } [Test] public void SelectableHydraulicBoundaryLocation_AlwaysOnChange_NotifyObserverAndCalculationPropertyChanged() { // Setup var newLocation = new TestHydraulicBoundaryLocation(); var selectableHydraulicBoundaryLocation = new SelectableHydraulicBoundaryLocation(newLocation, new Point2D(0, 0)); var newValue = new DataGridViewComboBoxItemWrapper(selectableHydraulicBoundaryLocation); var calculation = new PipingCalculationScenario(new GeneralPipingInput()); // Call & Assert SetPropertyAndVerifyNotificationsAndOutputForCalculation(row => row.SelectableHydraulicBoundaryLocation = newValue, calculation); } [Test] public void SelectableHydraulicBoundaryLocation_ChangeToEqualValue_NoNotificationsOutputNotCleared() { // Setup DataGridViewComboBoxItemWrapper oldValue = null; // Call AssertPropertyNotChanged( row => { oldValue = row.SelectableHydraulicBoundaryLocation; row.SelectableHydraulicBoundaryLocation = row.SelectableHydraulicBoundaryLocation; }, calculation => { // Assert Assert.NotNull(oldValue); Assert.AreEqual(oldValue.WrappedObject.HydraulicBoundaryLocation, calculation.InputParameters.HydraulicBoundaryLocation); }); } [Test] public void DampingFactorExitMean_AlwaysOnChange_NotifyObserverAndCalculationPropertyChanged() { // Setup var calculation = new PipingCalculationScenario(new GeneralPipingInput()); var dampingFactorExitMean = (RoundedDouble) 2.3; // Call & Assert SetPropertyAndVerifyNotificationsAndOutputForCalculation(row => row.DampingFactorExitMean = dampingFactorExitMean, calculation); } [Test] public void DampingFactorExitMean_ChangeToEqualValue_NoNotificationsOutputNotCleared() { // Setup RoundedDouble oldValue = RoundedDouble.NaN; // Call AssertPropertyNotChanged( row => { oldValue = row.DampingFactorExitMean; row.DampingFactorExitMean = row.DampingFactorExitMean; }, calculation => { // Assert Assert.False(double.IsNaN(oldValue)); Assert.AreEqual(oldValue, calculation.InputParameters.DampingFactorExit.Mean); }); } [Test] public void PhreaticLevelExitMean_AlwaysOnChange_NotifyObserverAndCalculationPropertyChanged() { // Setup var calculation = new PipingCalculationScenario(new GeneralPipingInput()); var phreaticLevelExitMean = (RoundedDouble) 5.1; // Call & Assert SetPropertyAndVerifyNotificationsAndOutputForCalculation(row => row.PhreaticLevelExitMean = phreaticLevelExitMean, calculation); } [Test] public void PhreaticLevelExitMean_ChangeToEqualValue_NoNotificationsOutputNotCleared() { // Setup RoundedDouble oldValue = RoundedDouble.NaN; // Call AssertPropertyNotChanged( row => { oldValue = row.PhreaticLevelExitMean; row.PhreaticLevelExitMean = row.PhreaticLevelExitMean; }, calculation => { // Assert Assert.False(double.IsNaN(oldValue)); Assert.AreEqual(oldValue, calculation.InputParameters.PhreaticLevelExit.Mean); }); } [Test] public void EntryPointL_OnValidChange_NotifyObserverAndCalculationPropertyChanged() { // Setup var calculation = new PipingCalculationScenario(new GeneralPipingInput()); var entryPointL = (RoundedDouble) 0.1; // Call & Assert SetPropertyAndVerifyNotificationsAndOutputForCalculation(row => row.EntryPointL = entryPointL, calculation); } [Test] public void EntryPointL_ChangeToEqualValue_NoNotificationsOutputNotCleared() { // Setup RoundedDouble oldValue = RoundedDouble.NaN; // Call AssertPropertyNotChanged( row => { oldValue = row.EntryPointL; row.EntryPointL = row.EntryPointL; }, calculation => { // Assert Assert.False(double.IsNaN(oldValue)); Assert.AreEqual(oldValue, calculation.InputParameters.EntryPointL); }); } [Test] [TestCase(0.2)] [TestCase(1.0)] public void EntryPointL_EntryPointNotBeforeExitPoint_ThrowsArgumentOutOfRangeExceptionDoesNotNotifyObservers(double newValue) { // Setup PipingCalculationScenario calculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithValidInput(new TestHydraulicBoundaryLocation()); var entryPointL = (RoundedDouble) newValue; // Call & Assert const string expectedMessage = "Het uittredepunt moet landwaarts van het intredepunt liggen."; SetPropertyToInvalidValueAndVerifyException(row => row.EntryPointL = entryPointL, calculation, expectedMessage); } [Test] [SetCulture("nl-NL")] public void EntryPointL_NotOnSurfaceLine_ThrowsArgumentOutOfRangeExceptionAndDoesNotNotifyObservers() { // Setup PipingCalculationScenario calculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithValidInput(new TestHydraulicBoundaryLocation()); var entryPointL = (RoundedDouble) (-3.0); // Call & Assert const string expectedMessage = "Het gespecificeerde punt moet op het profiel liggen (bereik [0,0, 1,0])."; SetPropertyToInvalidValueAndVerifyException(row => row.EntryPointL = entryPointL, calculation, expectedMessage); } [Test] public void ExitPointL_OnValidChange_NotifyObserverAndCalculationPropertyChanged() { // Setup PipingCalculationScenario calculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithValidInput(new TestHydraulicBoundaryLocation()); var exitPointL = (RoundedDouble) 0.3; // Call & Assert SetPropertyAndVerifyNotificationsAndOutputForCalculation(row => row.ExitPointL = exitPointL, calculation); } [Test] public void ExitPointL_ChangeToEqualValue_NoNotificationsOutputNotCleared() { // Setup RoundedDouble oldValue = RoundedDouble.NaN; // Call AssertPropertyNotChanged( row => { oldValue = row.ExitPointL; row.ExitPointL = row.ExitPointL; }, calculation => { // Assert Assert.False(double.IsNaN(oldValue)); Assert.AreEqual(oldValue, calculation.InputParameters.ExitPointL); }); } [Test] [TestCase(0.0)] [TestCase(-0.2)] public void ExitPointL_ExitPointNotBeyondEntryPoint_ThrowsArgumentOutOfRangeExceptionDoesNotNotifyObservers(double newValue) { // Setup PipingCalculationScenario calculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithValidInput(new TestHydraulicBoundaryLocation()); var exitPointL = (RoundedDouble) newValue; // Call & Assert const string expectedMessage = "Het uittredepunt moet landwaarts van het intredepunt liggen."; SetPropertyToInvalidValueAndVerifyException(row => row.ExitPointL = exitPointL, calculation, expectedMessage); } [Test] [SetCulture("nl-NL")] public void ExitPointL_NotOnSurfaceLine_ThrowsArgumentOutOfRangeExceptionAndDoesNotNotifyObservers() { // Setup PipingCalculationScenario calculation = PipingCalculationScenarioTestFactory.CreatePipingCalculationScenarioWithValidInput(new TestHydraulicBoundaryLocation()); var exitPointL = (RoundedDouble) 3.0; // Call & Assert const string expectedMessage = "Het gespecificeerde punt moet op het profiel liggen (bereik [0,0, 1,0])."; SetPropertyToInvalidValueAndVerifyException(row => row.ExitPointL = exitPointL, calculation, expectedMessage); } /// /// Asserts that the output of a remains /// unaffected (and therefore no change notification occurring) when the input for /// that calculation has been changed using an instance of . /// /// The function that changes a property of the /// instance. This function should not throw exceptions. /// The additional assertions to be performed on the /// whose input has been changed. private static void AssertPropertyNotChanged( Action setProperty, Action assertions) { AssertPropertyChangeWithOrWithoutCalculationOutput(setProperty, assertions, true, false); AssertPropertyChangeWithOrWithoutCalculationOutput(setProperty, assertions, false, false); } private static void AssertPropertyChangeWithOrWithoutCalculationOutput( Action setProperty, Action assertions, bool hasOutput, bool expectUpdates) { // Setup var mockRepository = new MockRepository(); var inputObserver = mockRepository.StrictMock(); if (expectUpdates) { inputObserver.Expect(o => o.UpdateObserver()); } var calculationObserver = mockRepository.StrictMock(); if (expectUpdates && hasOutput) { calculationObserver.Expect(o => o.UpdateObserver()); } var handler = mockRepository.Stub(); mockRepository.ReplayAll(); PipingOutput assignedOutput = null; var calculation = new PipingCalculationScenario(new GeneralPipingInput()); if (hasOutput) { assignedOutput = PipingOutputTestFactory.Create(); } calculation.Output = assignedOutput; var row = new PipingCalculationRow(calculation, handler); calculation.Attach(calculationObserver); calculation.InputParameters.Attach(inputObserver); // Call setProperty(row); // Assert assertions(calculation); if (expectUpdates) { Assert.IsNull(calculation.Output); } else { Assert.AreSame(assignedOutput, calculation.Output); } mockRepository.VerifyAll(); } private static void SetPropertyToInvalidValueAndVerifyException( Action setProperty, PipingCalculationScenario calculation, string expectedMessage) { // Setup var mocks = new MockRepository(); var observable = mocks.StrictMock(); mocks.ReplayAll(); var handler = new SetPropertyValueAfterConfirmationParameterTester( new[] { observable }); var row = new PipingCalculationRow(calculation, handler); // Call TestDelegate test = () => setProperty(row); // Assert TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, expectedMessage); Assert.IsTrue(handler.Called); mocks.VerifyAll(); } private static void SetPropertyAndVerifyNotificationsAndOutputForCalculation( Action setProperty, PipingCalculationScenario calculation) { // Setup var mocks = new MockRepository(); var observable = mocks.StrictMock(); observable.Expect(o => o.NotifyObservers()); mocks.ReplayAll(); var handler = new SetPropertyValueAfterConfirmationParameterTester( new[] { observable }); var row = new PipingCalculationRow(calculation, handler); // Call setProperty(row); // Assert Assert.IsTrue(handler.Called); mocks.VerifyAll(); } } }