public void ErrorMessages() { var tests = new ListOfTuples <string, string[]> { { "xa", new[] { "Contains A" } }, { "xb", new[] { "Contains B (abc, 123)", "Property:Name" } }, { "xc", new[] { "Contains C (xc, 2)" } }, { "xdddddd", new[] { "Property 'Simple2-Name' should not contain 'letter D'. The entered text is 'xdddddd', 7 characters long." } }, }; foreach (var test in tests) { using (var scope = TestScope.Create()) { Console.WriteLine("\r\nInput: " + test.Item1); var simple2 = scope.Resolve <Common.DomRepository>().TestInvalidData.Simple2; simple2.Delete(simple2.Query()); var newItem = new TestInvalidData.Simple2 { Name = test.Item1 }; var error = TestUtility.ShouldFail <Rhetos.UserException>( () => simple2.Insert(newItem), test.Item2); Console.WriteLine("ErrorMessage: " + ExceptionsUtility.MessageForLog(error)); Console.WriteLine("Exception: " + error.ToString()); } } }
public void GetErrorMessageMethodName() { var tests = new ListOfTuples <string, string, string>() { { "Mod.Ent", "Filt", "GetErrorMessage_Filt" }, { "Mod.Ent", "Mod.Filt", "GetErrorMessage_Filt" }, { "Mod.Ent", "Mod2.Filt", "GetErrorMessage_Mod2_2E_Filt" }, { "Mod.Ent", "Dictionary<List<System.Guid>, object[]>", "GetErrorMessage_Dictionary_3C_List_3C_System_2E_Guid_3E__2C__20_object_5B__5D__3E_" }, }; foreach (var test in tests) { Console.WriteLine("Input: " + test.Item1 + ", " + test.Item2 + "."); var dataStructureParts = test.Item1.Split('.'); var invalidData = new InvalidDataInfo { Source = new DataStructureInfo { Module = new ModuleInfo { Name = dataStructureParts[0] }, Name = dataStructureParts[1] }, FilterType = test.Item2, ErrorMessage = "[Test]" }; Assert.AreEqual(test.Item3, invalidData.GetErrorMessageMethodName()); } }
public void MaskPasswordTest() { var tests = new ListOfTuples <string, string[]> { // Format: connection string, expected content. { "Server=tcp:name.database.windows.net,1433;Initial Catalog=RhetosAzureDB;Persist Security Info=False;User ID=jjj;Password=jjj;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;", new[] { "tcp:name.database.windows.net,1433", "RhetosAzureDB" } }, { "Data Source=localhost;Initial Catalog=Rhetos;Integrated Security=SSPI;", new[] { "localhost", "Rhetos" } }, { "User Id=jjj;Password=jjj;Data Source=localhost:1521/xe;", new[] { "localhost:1521/xe" } }, { "User Id=jjj;Password='******';Data Source=localhost:1521/xe;", new[] { "localhost:1521/xe" } }, { "User Id=jjj;Password=\"jjj;jjj=jjj\";Data Source=localhost:1521/xe;", new[] { "localhost:1521/xe" } }, { "';[]=-", Array.Empty <string>() }, }; foreach (var test in tests) { Console.WriteLine(test.Item1); string report = SqlUtility.SqlConnectionInfo(test.Item1); Console.WriteLine("=> " + report); TestUtility.AssertNotContains(report, "j", "Username or password leaked."); if (test.Item2.Any()) { TestUtility.AssertContains(report, test.Item2); } } }
public void AbsoluteToRelativePath_LinuxAndMacOS() { var tests = new ListOfTuples <string, string, string>() { // Trivial: { "/Home", "/Home", "." }, { "/Home/1", "/Home", ".." }, { "/Home/1/", "/Home", ".." }, { "/Home/1", "/Home/1", @"." }, { "/Home/1/", "/Home/1", @"." }, { "/Home/1", "/Home/1/", @"." }, { "/Home/1/", "/Home/1/", @"." }, // Simple: { "/Home", "/Home/1", "1" }, { "/Home", "/Home/1/", "1" }, { "/Home/1", "/Home/2", "../2" }, { "/Home/1/", "/Home/2", "../2" }, { "/Home/1", "/Home/2/", "../2" }, { "/Home/1/", "/Home/2/", "../2" }, // Complex: { "/Home/11/22/33", "/Home/11/aaa/bbb/ccc", "../../aaa/bbb/ccc" }, { "/Home/11/22/33/aaa", "/Home/11/aaa/22/33", "../../../aaa/22/33" }, // Other root: { "/Home1/1", "/Home2/1", "/Home2/1" }, { "/Home1/1", "/Home2/2", "/Home2/2" }, }; foreach (var test in tests) { Assert.AreEqual( test.Item3, FilesUtility.AbsoluteToRelativePath(test.Item1, test.Item2), $"base:'{test.Item1}', target:'{test.Item2}'"); } }
public void AbsoluteToRelativePath_Windows() { var tests = new ListOfTuples <string, string, string>() { // Trivial: { @"C:\", @"C:\", @"." }, { @"C:\1", @"C:\", @".." }, { @"C:\1\", @"C:\", @".." }, { @"C:\1", @"C:\1", @"." }, { @"C:\1\", @"C:\1", @"." }, { @"C:\1", @"C:\1\", @"." }, { @"C:\1\", @"C:\1\", @"." }, // Simple: { @"C:\", @"C:\1", @"1" }, { @"C:\", @"C:\1\", @"1" }, { @"C:\1", @"C:\2", @"..\2" }, { @"C:\1\", @"C:\2", @"..\2" }, { @"C:\1", @"C:\2\", @"..\2" }, { @"C:\1\", @"C:\2\", @"..\2" }, // Complex: { @"C:\11\22\33", @"C:\11\aaa\bbb\ccc", @"..\..\aaa\bbb\ccc" }, { @"C:\11\22\33\aaa", @"C:\11\aaa\22\33", @"..\..\..\aaa\22\33" }, // Other disk: { @"C:\1", @"D:\1", @"D:\1" }, { @"C:\1", @"D:\2", @"D:\2" }, }; foreach (var test in tests) { Assert.AreEqual( test.Item3, FilesUtility.AbsoluteToRelativePath(test.Item1, test.Item2), $"base:'{test.Item1}', target:'{test.Item2}'"); } }
public void GetDatabaseTimeCached_BestLatency() { var tests = new ListOfTuples <ListOfTuples <int, double>, int> { // Format: 3 x (db latency ms, db clock offset seconds) => expected clock offset { new ListOfTuples <int, double> { { 20, 11 }, { 30, 22 }, { 40, 33 } }, 11 }, { new ListOfTuples <int, double> { { 40, 11 }, { 20, 22 }, { 30, 33 } }, 22 }, { new ListOfTuples <int, double> { { 40, 11 }, { 30, 22 }, { 20, 33 } }, 33 }, }; for (int t = 0; t < tests.Count(); t++) { var test = tests[t]; var dbUsage = new List <bool>(); TimeSpan lastDbOffset = TimeSpan.MaxValue; DatabaseTimeCache.Reset(); DateTime systemTime = new DateTime(2001, 2, 3, 4, 5, 6); foreach (var sqlClock in test.Item1.Concat(new[] { Tuple.Create <int, double>(70, 70) })) { DateTime dbTime = DateTime.MinValue; bool dbRead = false; DateTime computed = DatabaseTimeCache.GetDatabaseTimeCached( () => { dbRead = true; // There is no need to use Thred.Sleep(sqlClock.Item1) here, because db latency is simulated by increasing the systemTime value. return(dbTime = systemTime.AddSeconds(sqlClock.Item2)); }, () => { return(systemTime = systemTime.AddMilliseconds(sqlClock.Item1)); }); dbUsage.Add(dbRead); lastDbOffset = computed.Subtract(systemTime); Console.WriteLine($"Test {t} {sqlClock.Item1} {sqlClock.Item2}: sys {systemTime.ToString("o")}, db {dbTime.ToString("o")} " + $"=> {ReportDbOrCache(dbRead)} {computed.ToString("o")}"); } Assert.AreEqual("read db, read db, read db, read cache", TestUtility.Dump(dbUsage, ReportDbOrCache), $"Test {t}: Should use cache after 3rd query from database."); Assert.AreEqual(test.Item2, Convert.ToInt32(lastDbOffset.TotalSeconds), $"Test {t}: When using datetime cache, the database offset should be the one taken with the smallest latency."); } }
private void TestInterpretedException(ListOfTuples <Exception, string> tests) { var msSqlUtility = new MsSqlUtility(); foreach (var test in tests) { string reportInput = "Input: " + (test.Item1 != null ? test.Item1.ToString() : "null"); Console.WriteLine(reportInput); var interpretedException = msSqlUtility.InterpretSqlException(test.Item1); Console.WriteLine("Output: " + (interpretedException != null ? interpretedException.ToString() : "null")); Assert.AreEqual(test.Item2, Report(interpretedException), reportInput); } }
public void ReportSegment() { var tests = new ListOfTuples <string, int, int, string> { { "", -100, 3, "" }, { "", -1, 3, "" }, { "", 0, 3, "" }, { "", 1, 3, "" }, { "", 100, 3, "" }, { "abc", -1000, 100, "abc" }, { "abc", -10, 100, "abc" }, { "abc", 0, 100, "abc" }, { "abc", 10, 100, "abc" }, { "abc", 1000, 100, "abc" }, { "abcde", 0, 1, "a..." }, { "abcde", 1, 1, "...b..." }, { "abcde", 5, 1, "...e" }, { "abcde", -10, 3, "abc..." }, { "abcde", -1, 3, "abc..." }, { "abcde", 0, 3, "abc..." }, { "abcde", 1, 3, "abc..." }, { "abcde", 2, 3, "...bcd..." }, { "abcde", 3, 3, "...cde" }, { "abcde", 4, 3, "...cde" }, { "abcde", 5, 3, "...cde" }, { "abcde", 10, 3, "...cde" }, { "abcde", -10, 2, "ab..." }, { "abcde", -1, 2, "ab..." }, { "abcde", 0, 2, "ab..." }, { "abcde", 1, 2, "ab..." }, { "abcde", 2, 2, "...bc..." }, { "abcde", 3, 2, "...cd..." }, { "abcde", 4, 2, "...de" }, { "abcde", 5, 2, "...de" }, { "abcde", 10, 2, "...de" }, { "\r\n\t", 0, 1, @"\r..." }, { "\r\n\t", 1, 1, @"...\n..." }, { "\r\n\t", 2, 1, @"...\t" }, { "\r\n\t\\", 2, 10, @"\r\n\t\\" }, }; foreach (var test in tests) { Assert.AreEqual(test.Item4, CsUtility.ReportSegment(test.Item1, test.Item2, test.Item3), $"Test: {test.Item1} {test.Item2} {test.Item3}"); } }
public void LogCommandClientErrorDescription() { var log = new List <string>(); using (var scope = TestScope.Create(builder => builder .ConfigureLogMonitor(log) .ConfigureIgnoreClaims())) { var processingEngine = scope.Resolve <IProcessingEngine>(); var saveDuplicates = new SaveEntityCommandInfo { Entity = "TestUnique.E", DataToInsert = new[] { new TestUnique.E { I = 123, S = "abc" }, new TestUnique.E { I = 123, S = "abc" }, } }; var processingEngineResult = processingEngine.Execute(new[] { saveDuplicates }); Assert.IsFalse(processingEngineResult.Success); TestUtility.AssertContains(processingEngineResult.UserMessage, "duplicate"); var excected = new ListOfTuples <string, IEnumerable <string> >() { { "request info", new[] { "ProcessingEngine Request", "SaveEntityCommandInfo TestUnique.E, insert 2" } }, { "command xml", new[] { "ProcessingEngine Commands", "<DataToInsert", ">abc</S>" } }, { "error info", new[] { "Command failed: SaveEntityCommandInfo TestUnique.E, insert 2. Rhetos.UserException", "duplicate", "IX_E_S_I_R", "stack trace" } }, { "CommandsWithClientError xml", new[] { "ProcessingEngine CommandsWithClientError", "<DataToInsert", ">abc</S>" } }, { "CommandsWithClientError result", new[] { "ProcessingEngine CommandsWithClientError", "<UserMessage>", "It is not allowed" } }, }; foreach (var test in excected) { Assert.IsTrue(log.Any(line => test.Item2.All(pattern => line.Contains(pattern))), "Missing a log entry for test '" + test.Item1 + "'."); } var notExpected = new[] { "CommandsWithServerError" }; foreach (var test in notExpected) { Assert.IsFalse(log.Any(line => line.Contains(test)), "Unexpected log entry for test '" + test + "'."); } } }
private void RunTests(DateTime baseSysTime, TimeSpan dbOffset, ListOfTuples <int, double, bool> tests) { DatabaseTimeCache.Reset(); foreach (var test in tests) { DateTime systemTime = baseSysTime.AddMinutes(test.Item1).AddSeconds(test.Item2); DateTime dbTime = systemTime.Add(dbOffset); bool dbRead = false; DateTime computed = DatabaseTimeCache.GetDatabaseTimeCached(() => { dbRead = true; return(dbTime); }, () => systemTime); string report = $"Test {test.Item1} {test.Item2}: sys {systemTime.ToString("o")}, db {dbTime.ToString("o")} " + $"=> {ReportDbOrCache(dbRead)} {computed.ToString("o")}"; Console.WriteLine(report); Assert.AreEqual(ReportDbOrCache(test.Item3), ReportDbOrCache(dbRead), report); Assert.AreEqual(dbTime, computed, report); } }
private void TestDifferentConceptSameKey(ListOfTuples <IConceptInfo[], string, string, string[]> newConceptsSets) { var dslContainer = new DslContainerAccessor(); foreach (var newConceptsSet in newConceptsSets) { if (newConceptsSet.Item4 == null) { var report = dslContainer.AddNewConceptsAndReplaceReferences(newConceptsSet.Item1); Assert.AreEqual(newConceptsSet.Item2, TestUtility.DumpSorted(report.NewUniqueConcepts, item => item.GetShortDescription())); Assert.AreEqual(newConceptsSet.Item3, TestUtility.DumpSorted(dslContainer.Concepts, item => item.GetShortDescription())); } else { TestUtility.ShouldFail(() => dslContainer.AddNewConceptsAndReplaceReferences(newConceptsSet.Item1), newConceptsSet.Item4); } } }
public void LogCommandDescription() { var log = new List <string>(); using (var scope = TestScope.Create(builder => builder .ConfigureLogMonitor(log) .ConfigureIgnoreClaims())) { var processingEngine = scope.Resolve <IProcessingEngine>(); var readPrincipals = new ReadCommandInfo { DataSource = "Common.Principal", ReadTotalCount = true, Filters = new[] { new FilterCriteria { Filter = "System.Guid[]", Value = new[] { new Guid("546df18b-5df8-4ffa-9b08-8da909efe067") } } } }; var processingEngineResult = processingEngine.Execute(new[] { readPrincipals }); Assert.IsTrue(processingEngineResult.Success); var excected = new ListOfTuples <string, IEnumerable <string> >() { { "request info", new[] { "ProcessingEngine Request", "ReadCommandInfo Common.Principal count, filters: System.Guid[] \"1 items: 546df18b-5df8-4ffa-9b08-8da909efe067\"" } }, { "command xml", new[] { "ProcessingEngine Commands", "Common.Principal</DataSource>", "true</ReadTotalCount>" } }, }; foreach (var test in excected) { Assert.IsTrue(log.Any(line => test.Item2.All(pattern => line.Contains(pattern))), "Missing a log entry for test '" + test.Item1 + "'."); } var notExpected = new[] { "error info", "CommandsWithClientError", "CommandsWithClientError", "CommandsWithServerError", "CommandsWithServerError" }; foreach (var test in notExpected) { Assert.IsFalse(log.Any(line => line.Contains(test)), "Unexpected log entry for test '" + test + "'."); } } }
public void JoinScriptsTest() { // input scripts, max count, max size, expected output scripts // "//" is a shortcut for "\r\n" var tests = new ListOfTuples <string[], int, int, string[]> { { new string[] { }, 10, 1000, new string[] { } }, { new string[] { }, 0, 0, new string[] { } }, { new[] { "a", "b", "c" }, 10, 1000, new[] { "a//b//c" } }, { new[] { "12345", "12345", "12345" }, 3, 1000, new[] { "12345//12345//12345" } }, { new[] { "12345", "12345", "12345" }, 2, 1000, new[] { "12345//12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 1, 1000, new[] { "12345", "12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 0, 1000, new[] { "12345", "12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 3, 19, new[] { "12345//12345//12345" } }, { new[] { "12345", "12345", "12345" }, 3, 18, new[] { "12345//12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 3, 12, new[] { "12345//12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 3, 11, new[] { "12345", "12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 3, 5, new[] { "12345", "12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 3, 1, new[] { "12345", "12345", "12345" } }, { new[] { "12345", "12345", "12345" }, 3, 0, new[] { "12345", "12345", "12345" } }, }; foreach (var test in tests) { var options = new SqlTransactionBatchesOptions { MaxJoinedScriptCount = test.Item2, MaxJoinedScriptSize = test.Item3, }; var batches = new SqlTransactionBatches(null, options, new ConsoleLogProvider(), new DelayedLogProvider(new LoggingOptions { DelayedLogTimout = 0 }, null)); var joinedScripts = batches.JoinScripts(test.Item1); Assert.AreEqual( TestUtility.Dump(test.Item4), TestUtility.Dump(joinedScripts.Select(s => s.Replace("\r\n", "//"))), $"Test: '{TestUtility.Dump(test.Item1)}' - {test.Item2}, {test.Item3} => {joinedScripts.Count}, {joinedScripts.Sum(s => s.Length)}"); } }
public void SafeFormatMessage() { var tests = new ListOfTuples<Exception, string> { { new Exception("abc"), "abc" }, { new UserException("abc"), "abc" }, { new UserException("abc", null, null, null), "abc" }, { new UserException("abc", new object[] { 123 }, null, null), "abc" }, { new UserException("a{0}bc", new object[] { 123, 456 }, null, null), "a123bc" }, { new UserException("a{1}bc", new object[] { 123 }, null, null), "Invalid error message format. Message: \"a{1}bc\", Parameters: \"123\", FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list." }, { new UserException("a{0}bc", null, null, null), "Invalid error message format. Message: \"a{0}bc\", Parameters: null, FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list." }, }; foreach (var test in tests) { Console.WriteLine("Test: " + test.Item1.ToString()); string result = ExceptionsUtility.SafeFormatUserMessage(test.Item1); Assert.AreEqual(test.Item2, result); } }
public void SafeFormatMessage() { var tests = new ListOfTuples <Exception, string> { { new Exception("abc"), "abc" }, { new UserException("abc"), "abc" }, { new UserException("abc", null, null, null), "abc" }, { new UserException("abc", new object[] { 123 }, null, null), "abc" }, { new UserException("a{0}bc", new object[] { 123, 456 }, null, null), "a123bc" }, { new UserException("a{1}bc", new object[] { 123 }, null, null), "Invalid error message format. Message: \"a{1}bc\", Parameters: \"123\", FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list." }, { new UserException("a{0}bc", null, null, null), "Invalid error message format. Message: \"a{0}bc\", Parameters: null, FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list." }, }; foreach (var test in tests) { Console.WriteLine("Test: " + test.Item1.ToString()); string result = ExceptionsUtility.MessageForLog(test.Item1); Assert.AreEqual(test.Item2, result); } }
public void InsertMultipleItems() { using (var container = new RhetosTestContainer()) { DeleteOldData(container); var repository = container.Resolve <Common.DomRepository>(); var tests = new ListOfTuples <string, string> { { "+", "10" }, // Exactly specified values are considered before generated values, therefore this item is handled after core "9". { "+", "11" }, { "+", "12" }, { "9", "9" }, { "+", "13" }, { "+", "14" }, { "AB+", "AB1000" }, { "X", "X" }, { "X+", "X1" }, { "AB007", "AB007" }, { "AB+", "AB1001" }, { "AB999", "AB999" }, { "AB+", "AB1002" }, }; repository.TestAutoCode.Simple.Insert( tests.Select((test, index) => new TestAutoCode.Simple { ID = new Guid(index + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Code = test.Item1 })); IEnumerable <string> generatedCodes = repository.TestAutoCode.Simple.Load() .OrderBy(item => item.ID) .Select(item => item.Code); IEnumerable <string> expectedCodes = tests.Select(test => test.Item2); Assert.AreEqual(TestUtility.Dump(expectedCodes), TestUtility.Dump(generatedCodes)); } }
public void GetErrorMessageMethodName() { var tests = new ListOfTuples<string, string, string>() { { "Mod.Ent", "Filt", "GetErrorMessage_Filt" }, { "Mod.Ent", "Mod.Filt", "GetErrorMessage_Filt" }, { "Mod.Ent", "Mod2.Filt", "GetErrorMessage_Mod2_2E_Filt" }, { "Mod.Ent", "Dictionary<List<System.Guid>, object[]>", "GetErrorMessage_Dictionary_3C_List_3C_System_2E_Guid_3E__2C__20_object_5B__5D__3E_" }, }; foreach (var test in tests) { Console.WriteLine("Input: " + test.Item1 + ", " + test.Item2 + "."); var dataStructureParts = test.Item1.Split('.'); var invalidData = new InvalidDataInfo { Source = new DataStructureInfo { Module = new ModuleInfo { Name = dataStructureParts[0] }, Name = dataStructureParts[1] }, FilterType = test.Item2, ErrorMessage = "[Test]" }; Assert.AreEqual(test.Item3, invalidData.GetErrorMessageMethodName()); } }
public void FirstLine() { var tests = new ListOfTuples <string, string> { { "abc", "abc" }, { "", "" }, { null, null }, { "abc\r\ndef\r\n123", "abc" }, { "a\r\ndef", "a" }, { "\r\ndef", "" }, { "\r\ndef\r\n", "" }, { "\r\ndef\r\n1234", "" }, { "\r", "" }, { "\n", "" }, { "abc\rdef\n123", "abc" }, { "abc\ndef\r123", "abc" }, }; foreach (var test in tests) { Assert.AreEqual(test.Item2, CsUtility.FirstLine(test.Item1), "Test: " + test.Item1); } }
public void LogCommandServerErrorDescription() { var log = new List <string>(); using (var scope = TestScope.Create(builder => builder .ConfigureLogMonitor(log) .ConfigureIgnoreClaims())) { var readCommandError = new ReadCommandInfo() { DataSource = "TestRowPermissions.ErrorData", ReadRecords = true, Filters = new[] { new FilterCriteria("duplicateSecondItem") } }; var processingEngine = scope.Resolve <IProcessingEngine>(); var processingEngineResult = processingEngine.Execute(new[] { readCommandError }); Assert.IsFalse(processingEngineResult.Success); TestUtility.AssertContains(processingEngineResult.SystemMessage, new[] { "Internal server error occurred", "IndexOutOfRangeException" }); var excected = new ListOfTuples <string, IEnumerable <string> >() { { "error info", new[] { "Command failed: ReadCommandInfo TestRowPermissions.ErrorData", "Index was outside the bounds of the array", "stack trace" } }, { "CommandsWithServerError xml", new[] { "ProcessingEngine CommandsWithServerError", "TestRowPermissions.ErrorData</DataSource>" } }, { "CommandsWithServerError result", new[] { "ProcessingEngine CommandsWithServerError", "<SystemMessage>", "Internal server error" } }, }; foreach (var test in excected) { Assert.IsTrue(log.Any(line => test.Item2.All(pattern => line.Contains(pattern))), "Missing a log entry for test '" + test.Item1 + "'."); } var notExpected = new[] { "CommandsWithClientError" }; foreach (var test in notExpected) { Assert.IsFalse(log.Any(line => line.Contains(test)), "Unexpected log entry for test '" + test + "'."); } } }
public void ErrorMessages() { var tests = new ListOfTuples<string, string[]> { { "xa", new[] { "Contains A" } }, { "xb", new[] { "Contains B (abc, 123)", "Property:Name" } }, { "xc", new[] { "Contains C (xc, 2)" } }, { "xdddddd", new[] { "Property 'Simple2-Name' should not contain 'letter D'. The entered text is 'xdddddd', 7 characters long." } }, }; foreach (var test in tests) { using (var container = new RhetosTestContainer()) { Console.WriteLine("\r\nInput: " + test.Item1); var simple2 = container.Resolve<Common.DomRepository>().TestInvalidData.Simple2; simple2.Delete(simple2.Query()); var newItem = new TestInvalidData.Simple2 { Name = test.Item1 }; var error = TestUtility.ShouldFail<Rhetos.UserException>( () => simple2.Insert(newItem), test.Item2); Console.WriteLine("ErrorMessage: " + ExceptionsUtility.SafeFormatUserMessage(error)); Console.WriteLine("Exception: " + error.ToString()); } } }
private void TestDifferentConceptSameKey(ListOfTuples<IConceptInfo[], string, string, string[]> newConceptsSets) { var dslContainer = new DslContainerAccessor(); foreach (var newConceptsSet in newConceptsSets) { if (newConceptsSet.Item4 == null) { var report = dslContainer.AddNewConceptsAndReplaceReferences(newConceptsSet.Item1); Assert.AreEqual(newConceptsSet.Item2, TestUtility.DumpSorted(report.NewUniqueConcepts, item => item.GetShortDescription())); Assert.AreEqual(newConceptsSet.Item3, TestUtility.DumpSorted(dslContainer.Concepts, item => item.GetShortDescription())); } else { TestUtility.ShouldFail(() => dslContainer.AddNewConceptsAndReplaceReferences(newConceptsSet.Item1), newConceptsSet.Item4); } } }
public void OptimizeParallelInsertsForDifferentGroups() { var tests = new ListOfTuples <string, string, bool> // Format: // 1. Records to insert (Grouping1-Grouping2) to entity MultipleGroups, with parallel requests. // 2. Expected generated codes (Code1-Code2) for each record. // 3. Whether the inserts should be executed in parallel. { { "A-B, A-B", "1-1, 2-2", false }, // Same Grouping1 and Grouping2: codes should be generated sequentially. { "A-B, A-C", "1-1, 2-1", false }, // Same Grouping1: Code1 should be generated sequentially. { "A-B, C-B", "1-1, 1-2", false }, // Same Grouping2: Code2 should be generated sequentially. { "A-B, C-D", "1-1, 1-1", true }, { "A-B, B-A", "1-1, 1-1", true }, }; var results = new ListOfTuples <string, string, bool>(); var report = new List <string>(); const int testPause = 100; const int retries = 4; foreach (var test in tests) { for (int retry = 0; retry < retries; retry++) { var items = test.Item1.Split(',').Select(item => item.Trim()).Select(item => item.Split('-')) .Select(item => new TestAutoCode.MultipleGroups { Grouping1 = item[0], Grouping2 = item[1] }) .ToArray(); var insertDurations = new double[items.Length]; var parallelInsertRequests = items.Select((item, x) => (Action <Common.ExecutionContext>) (context => { var sw = Stopwatch.StartNew(); context.Repository.TestAutoCode.MultipleGroups.Insert(item); insertDurations[x] = sw.Elapsed.TotalMilliseconds; Thread.Sleep(testPause); })) .ToArray(); var exceptions = ExecuteParallel(parallelInsertRequests, context => context.Repository.TestAutoCode.MultipleGroups.Insert(new TestAutoCode.MultipleGroups { }), context => Assert.AreEqual(1, context.Repository.TestAutoCode.MultipleGroups.Query().Count(), $"({test.Item1}) Test initialization failed.")); Assert.IsTrue(exceptions.All(e => e == null), $"({test.Item1}) Test initialization threw exception. See the test output for details"); // Check the generated codes: string generatedCodes; using (var container = new RhetosTestContainer(false)) { var repository = container.Resolve <Common.DomRepository>(); generatedCodes = TestUtility.DumpSorted( repository.TestAutoCode.MultipleGroups.Load(items.Select(item => item.ID)), x => $"{x.Code1}-{x.Code2}"); } // Check if the inserts were executed in parallel: bool startedImmediately = insertDurations.Any(t => t < testPause); bool executedInParallel = insertDurations.All(t => t < testPause); // It the parallelism check did not pass, try again to reduce false negatives when the test machine is under load. if (!startedImmediately || executedInParallel != test.Item3) { Console.WriteLine("Retry"); continue; } Assert.IsTrue(startedImmediately, $"({test.Item1}) At lease one item should be inserted without waiting. The test machine was probably under load during the parallelism test."); report.Add($"Test '{test.Item1}' insert durations: '{TestUtility.Dump(insertDurations)}'."); results.Add(test.Item1, generatedCodes, executedInParallel); break; } } Assert.AreEqual( string.Concat(tests.Select(test => $"{test.Item1} => {test.Item2} {(test.Item3 ? "parallel" : "sequential")}\r\n")), string.Concat(results.Select(test => $"{test.Item1} => {test.Item2} {(test.Item3 ? "parallel" : "sequential")}\r\n")), "Report: " + string.Concat(report.Select(line => "\r\n" + line))); }