void FileTests::TestReadFileBasicEmpty() { HANDLE const hIn = GetStdInputHandle(); VERIFY_IS_NOT_NULL(hIn, L"Verify we have the standard input handle."); DWORD dwMode = 0; VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hIn, dwMode), L"Set input mode for test."); VERIFY_WIN32_BOOL_SUCCEEDED(FlushConsoleInputBuffer(hIn), L"Flush input buffer in preparation for test."); char ch = '\0'; Log::Comment(L"Queue background blocking read file operation."); auto BackgroundRead = std::async([&] { DWORD dwRead = 0; VERIFY_WIN32_BOOL_SUCCEEDED(ReadFile(hIn, &ch, 1, &dwRead, nullptr), L"Read file was successful."); VERIFY_ARE_EQUAL(0u, dwRead, L"We should have read nothing back. It should just return from Ctrl+Z"); }); char const chExpected = '\x1a'; // ctrl+z character Log::Comment(L"Send a key into the console."); SendFullKeyStrokeHelper(hIn, chExpected); Log::Comment(L"Wait for background to unblock."); BackgroundRead.wait(); VERIFY_ARE_EQUAL('\0', ch); }
TEST_FIXTURE(e2e_raw_client, update_entity_with_patch) { auto model = client.get_model().get(); //check the old value auto query_result = client.get_data_from_server(U("Accounts(101)")).get(); auto old_entity = std::dynamic_pointer_cast<odata_entity_value>(query_result[0]); std::shared_ptr<odata_value> old_value; old_entity->get_property_value(U("Country"), old_value); auto old_country = std::dynamic_pointer_cast<odata_primitive_value>(old_value); VERIFY_ARE_EQUAL(U("US"), old_country->as<::utility::string_t>()); //update the entity with patch old_entity->set_value(U("Country"), U("GB")); auto response_code = client.patch_entity(U("Accounts"), old_entity).get(); VERIFY_ARE_EQUAL(204, response_code); //query the updated entity auto check_query = client.get_data_from_server(U("Accounts(101)")).get(); auto new_entity = std::dynamic_pointer_cast<odata_entity_value>(check_query[0]); std::shared_ptr<odata_value> property_value; VERIFY_IS_TRUE(new_entity->get_property_value(U("Country"), property_value)); auto primitive_value = std::dynamic_pointer_cast<odata_primitive_value>(property_value); ::utility::string_t new_country = primitive_value->as<::utility::string_t>(); VERIFY_ARE_EQUAL(U("GB"), new_country); }
TEST_FIXTURE(e2e_raw_client, create_entity) { auto model = client.get_model().get(); ::utility::string_t entity_set_name = U("Accounts"); std::shared_ptr<odata_entity_value> entity = std::make_shared<odata_entity_value>(model->find_entity_set_type(entity_set_name)); entity->set_value(U("AccountID"), 130); entity->set_value(U("Country"), U("CN")); auto accountinfo_type = model->find_complex_type(U("AccountInfo")); auto account_info = std::make_shared<odata_complex_value>(accountinfo_type); ::utility::string_t account_firstname = U("cpp"); ::utility::string_t account_lastname = U("client"); account_info->set_value(U("FirstName"), account_firstname); account_info->set_value(U("LastName"), account_lastname); entity->set_value(U("AccountInfo"), account_info); auto response_code = client.create_entity(entity_set_name, entity).get(); VERIFY_ARE_EQUAL(201, response_code); //query the newly created entity auto query_result = client.get_data_from_server(U("Accounts(130)")).get(); VERIFY_ARE_EQUAL(query_result.size(), 1); auto new_entity = std::dynamic_pointer_cast<odata_entity_value>(query_result[0]); std::shared_ptr<odata_value> property_value; VERIFY_IS_TRUE(entity->get_property_value(U("AccountID"), property_value)); auto primitive_value = std::dynamic_pointer_cast<odata_primitive_value>(property_value); int32_t new_id = primitive_value->as<int32_t>(); VERIFY_ARE_EQUAL(130, new_id); }
void FontTests::TestGetFontSizeLargeIndexInvalid() { SetLastError(0); COORD coordFontSize = OneCoreDelay::GetConsoleFontSize(GetStdOutputHandle(), 0xFFFFFFFF); VERIFY_ARE_EQUAL(coordFontSize, c_coordZero, L"Ensure (0,0) coord returned to indicate failure"); VERIFY_ARE_EQUAL(GetLastError(), (DWORD)ERROR_INVALID_PARAMETER, L"Ensure last error was set appropriately"); }
void FileTests::TestWriteFileDisableNewlineAutoReturn() { bool fDisableAutoReturn; VERIFY_SUCCEEDED(TestData::TryGetValue(L"fDisableAutoReturn", fDisableAutoReturn)); bool fProcessedOn; VERIFY_SUCCEEDED(TestData::TryGetValue(L"fProcessedOn", fProcessedOn)); HANDLE const hOut = GetStdOutputHandle(); VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle."); CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 }; csbiexOriginal.cbSize = sizeof(csbiexOriginal); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test."); DWORD dwMode = 0; WI_SetFlagIf(dwMode, DISABLE_NEWLINE_AUTO_RETURN, fDisableAutoReturn); WI_SetFlagIf(dwMode, ENABLE_PROCESSED_OUTPUT, fProcessedOn); VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, dwMode), L"Set console mode for test."); COORD const coordZero = { 0 }; VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer."); CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 }; csbiexBefore.cbSize = sizeof(csbiexBefore); CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 }; csbiexAfter.cbSize = sizeof(csbiexAfter); COORD coordExpected = { 0 }; WriteFileHelper(hOut, csbiexBefore, csbiexAfter, "abc", 3); coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X += 3; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Cursor should have moved right to the end of the text written."); WriteFileHelper(hOut, csbiexBefore, csbiexAfter, "\n", 1); if (fProcessedOn) { if (fDisableAutoReturn) { coordExpected = csbiexBefore.dwCursorPosition; coordExpected.Y += 1; } else { coordExpected = csbiexBefore.dwCursorPosition; coordExpected.Y += 1; coordExpected.X = 0; } } else { coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X += 1; } VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Cursor should move to expected position."); }
void FileTests::TestWriteFileVTProcessing() { bool fVtOn; VERIFY_SUCCEEDED(TestData::TryGetValue(L"fVtOn", fVtOn)); bool fProcessedOn; VERIFY_SUCCEEDED(TestData::TryGetValue(L"fProcessedOn", fProcessedOn)); HANDLE const hOut = GetStdOutputHandle(); VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle."); CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 }; csbiexOriginal.cbSize = sizeof(csbiexOriginal); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test."); DWORD dwFlags = 0; WI_SetFlagIf(dwFlags, ENABLE_VIRTUAL_TERMINAL_PROCESSING, fVtOn); WI_SetFlagIf(dwFlags, ENABLE_PROCESSED_OUTPUT, fProcessedOn); VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, dwFlags), L"Turn on relevant flags for test."); COORD const coordZero = { 0 }; VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer."); PCSTR pszTestString = "\x1b" "[14m"; DWORD const cchTest = (DWORD)strlen(pszTestString); CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 }; csbiexBefore.cbSize = sizeof(csbiexBefore); CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 }; csbiexAfter.cbSize = sizeof(csbiexAfter); WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTestString, cchTest); // We only expect characters to be processed and not printed if both processed mode and VT mode are on. bool const fProcessedNotPrinted = fProcessedOn && fVtOn; if (fProcessedNotPrinted) { PCSTR pszReadBackExpected = " "; DWORD const cchReadBackExpected = (DWORD)strlen(pszReadBackExpected); VERIFY_ARE_EQUAL(csbiexBefore.dwCursorPosition, csbiexAfter.dwCursorPosition, L"Verify cursor didn't move because the VT sequence was processed instead of printed."); wistd::unique_ptr<char[]> pszReadBack; ReadBackHelper(hOut, coordZero, cchReadBackExpected, pszReadBack); VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify that nothing was printed into the buffer."); } else { COORD coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X += (SHORT)cchTest; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved as characters should have been emitted, not consumed."); wistd::unique_ptr<char[]> pszReadBack; ReadBackHelper(hOut, coordZero, cchTest, pszReadBack); VERIFY_ARE_EQUAL(String(pszTestString), String(pszReadBack.get()), L"Verify that original test string was printed into the buffer."); } }
void TestSetConsoleCursorPositionImpl(WORD wCursorX, WORD wCursorY, BOOL bExpectedResult) { COORD coordCursor; coordCursor.X = wCursorX; coordCursor.Y = wCursorY; // Get initial position data CONSOLE_SCREEN_BUFFER_INFOEX sbiInitial = { 0 }; sbiInitial.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); BOOL bResult = GetConsoleScreenBufferInfoEx(Common::_hConsole, &sbiInitial); VERIFY_WIN32_BOOL_SUCCEEDED(bResult, L"Get the initial buffer data."); // Attempt to set cursor into valid area bResult = SetConsoleCursorPosition(Common::_hConsole, coordCursor); VERIFY_ARE_EQUAL(bResult, bExpectedResult, L"Ensure that return from SET matches success/failure state we were expecting."); CONSOLE_SCREEN_BUFFER_INFOEX sbiTest = { 0 }; sbiTest.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); bResult = GetConsoleScreenBufferInfoEx(Common::_hConsole, &sbiTest); VERIFY_WIN32_BOOL_SUCCEEDED(bResult, L"GET the values back to ensure they were set properly."); // Cursor is where it was set to if we were supposed to be successful if (bExpectedResult) { VERIFY_ARE_EQUAL(coordCursor, sbiTest.dwCursorPosition, L"If SET was TRUE, we expect the cursor to be where we SET it."); } else { // otherwise, it's at where it was before VERIFY_ARE_EQUAL(sbiInitial.dwCursorPosition, sbiTest.dwCursorPosition, L"If SET was FALSE, we expect the cursor to not have moved."); } // Verify the viewport. bool fViewportMoveExpected = false; // If we expected the cursor to be set successfully, the viewport might have moved. if (bExpectedResult) { // If the position we set was outside the initial rectangle, then the viewport should have moved. if (coordCursor.X > sbiInitial.srWindow.Right || coordCursor.X < sbiInitial.srWindow.Left || coordCursor.Y > sbiInitial.srWindow.Bottom || coordCursor.Y < sbiInitial.srWindow.Top) { fViewportMoveExpected = true; } } if (fViewportMoveExpected) { // Something had to have changed in the viewport VERIFY_ARE_NOT_EQUAL(sbiInitial.srWindow, sbiTest.srWindow, L"The viewports must have changed if we set the cursor outside the current area."); } else { VERIFY_ARE_EQUAL(sbiInitial.srWindow, sbiTest.srWindow, L"The viewports must remain the same if the cursor was set inside the existing one."); } }
TEST_FIXTURE(e2e_raw_client, query_collection_property) { auto query_result = client.get_data_from_server(U("People(4)/Numbers")).get(); VERIFY_ARE_EQUAL(query_result.size(), 3); VERIFY_ARE_EQUAL(edm_type_kind_t::Primitive, query_result[0]->get_value_type()->get_type_kind()); auto primitive_value = std::dynamic_pointer_cast<odata_primitive_value>(query_result[1]); ::utility::string_t number = primitive_value->as<::utility::string_t>(); VERIFY_ARE_EQUAL(U("555-555-5555"), number); }
void FileTests::TestWriteFileWrapEOL() { bool fFlagOn; VERIFY_SUCCEEDED(TestData::TryGetValue(L"fFlagOn", fFlagOn)); HANDLE const hOut = GetStdOutputHandle(); VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle."); CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 }; csbiexOriginal.cbSize = sizeof(csbiexOriginal); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test."); if (fFlagOn) { VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT), L"Set wrap at EOL."); } else { VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, 0), L"Make sure wrap at EOL is off."); } COORD const coordZero = { 0 }; VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer."); // Fill first row of the buffer with Z characters until 1 away from the end. for (SHORT i = 0; i < csbiexOriginal.dwSize.X - 1; i++) { WriteFile(hOut, "Z", 1, nullptr, nullptr); } CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 }; csbiexBefore.cbSize = sizeof(csbiexBefore); CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 }; csbiexAfter.cbSize = sizeof(csbiexAfter); COORD coordExpected = { 0 }; VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexBefore), L"Get cursor position information before attempting to wrap at end of line."); VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, "Y", 1, nullptr, nullptr), L"Write of final character in line succeeded."); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexAfter), L"Get cursor position information after attempting to wrap at end of line."); if (fFlagOn) { Log::Comment(L"Cursor should go down a row if we tried to print at end of line."); coordExpected = csbiexBefore.dwCursorPosition; coordExpected.Y++; coordExpected.X = 0; } else { Log::Comment(L"Cursor shouldn't move when printing at end of line."); coordExpected = csbiexBefore.dwCursorPosition; } VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved as expected based on flag state."); }
void FontTests::TestGetFontSizeInvalid() { DWORD dwConsoleOutput; VERIFY_SUCCEEDED(TestData::TryGetValue(L"dwConsoleOutput", dwConsoleOutput), L"Get input handle value"); // Need to make sure that last error is cleared so that we can verify that lasterror was set by GetConsoleFontSize SetLastError(0); COORD coordFontSize = OneCoreDelay::GetConsoleFontSize((HANDLE)dwConsoleOutput, 0); VERIFY_ARE_EQUAL(coordFontSize, c_coordZero, L"Ensure (0,0) coord returned to indicate failure"); VERIFY_ARE_EQUAL(GetLastError(), (DWORD)ERROR_INVALID_HANDLE, L"Ensure last error was set appropriately"); }
void FileTests::TestUtf8WriteFileInvalid() { Log::Comment(L"Backup original console codepage."); UINT const uiOriginalCP = GetConsoleOutputCP(); auto restoreOriginalCP = wil::scope_exit([&] { Log::Comment(L"Restore original console codepage."); SetConsoleOutputCP(uiOriginalCP); }); HANDLE const hOut = GetStdOutputHandle(); VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle."); VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleOutputCP(CP_UTF8), L"Set output codepage to UTF8"); DWORD dwWritten; DWORD dwExpectedWritten; char* str; DWORD cbStr; // \x80 is an invalid UTF-8 continuation // \x40 is the @ symbol which is valid. str = "\x80\x40"; cbStr = (DWORD)strlen(str); dwWritten = 0; dwExpectedWritten = cbStr; VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, str, cbStr, &dwWritten, nullptr)); VERIFY_ARE_EQUAL(dwExpectedWritten, dwWritten); // \x80 is an invalid UTF-8 continuation // \x40 is the @ symbol which is valid. str = "\x80\x40\x40"; cbStr = (DWORD)strlen(str); dwWritten = 0; dwExpectedWritten = cbStr; VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, str, cbStr, &dwWritten, nullptr)); VERIFY_ARE_EQUAL(dwExpectedWritten, dwWritten); // \x80 is an invalid UTF-8 continuation // \x40 is the @ symbol which is valid. str = "\x80\x80\x80\x40"; cbStr = (DWORD)strlen(str); dwWritten = 0; dwExpectedWritten = cbStr; VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, str, cbStr, &dwWritten, nullptr)); VERIFY_ARE_EQUAL(dwExpectedWritten, dwWritten); }
void FontTests::TestLongFontNameScenario() { wistd::unique_ptr<wchar_t[]> expandedLongFontPath; VERIFY_SUCCEEDED(ExpandPathToMutable(pwszLongFontPath, expandedLongFontPath)); if (!CheckIfFileExists(expandedLongFontPath.get())) { Log::Comment(L"Lucida Sans Typewriter doesn't exist; skipping long font test."); Log::Result(WEX::Logging::TestResults::Result::Skipped); return; } const HANDLE hConsoleOutput = GetStdOutputHandle(); CONSOLE_FONT_INFOEX cfieSetLong = { 0 }; cfieSetLong.cbSize = sizeof(cfieSetLong); cfieSetLong.FontFamily = 54; cfieSetLong.dwFontSize.Y = 12; VERIFY_SUCCEEDED(StringCchCopy(cfieSetLong.FaceName, ARRAYSIZE(cfieSetLong.FaceName), L"Lucida Sans Typewriter")); VERIFY_WIN32_BOOL_SUCCEEDED(OneCoreDelay::SetCurrentConsoleFontEx(hConsoleOutput, FALSE, &cfieSetLong)); CONSOLE_FONT_INFOEX cfiePostLong = { 0 }; cfiePostLong.cbSize = sizeof(cfiePostLong); VERIFY_WIN32_BOOL_SUCCEEDED(OneCoreDelay::GetCurrentConsoleFontEx(hConsoleOutput, FALSE, &cfiePostLong)); Log::Comment(NoThrowString().Format(L"%ls %ls", cfieSetLong.FaceName, cfiePostLong.FaceName)); VERIFY_ARE_EQUAL(0, NoThrowString(cfieSetLong.FaceName).CompareNoCase(cfiePostLong.FaceName)); }
void FileTests::TestWriteFileSuspended() { HANDLE const hOut = GetStdOutputHandle(); VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle."); HANDLE const hIn = GetStdInputHandle(); VERIFY_IS_NOT_NULL(hIn, L"Verify we have the standard input handle."); CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 }; csbiexOriginal.cbSize = sizeof(csbiexOriginal); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test."); DWORD dwMode = 0; VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, dwMode), L"Set console mode for test."); COORD const coordZero = { 0 }; VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer."); VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, "abc", 3, nullptr, nullptr), L"Test first write success."); PauseHelper(hIn); auto BlockedWrite = std::async([&] { Log::Comment(L"Background WriteFile scheduled."); VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, "def", 3, nullptr, nullptr), L"Test second write success."); }); UnpauseHelper(hIn); BlockedWrite.wait(); }
void FileTests::TestWriteFileRaw() { // \x7 is bell // \x8 is backspace // \x9 is tab // \xa is linefeed // \xd is carriage return // All should be ignored/printed in raw mode. PCSTR strTest = "z\x7y\x8z\x9y\xaz\xdy"; DWORD const cchTest = (DWORD)strlen(strTest); String strReadBackExpected(strTest); HANDLE const hOut = GetStdOutputHandle(); VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle."); CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 }; csbiexBefore.cbSize = sizeof(csbiexBefore); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexBefore), L"Retrieve screen buffer properties before writing."); VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, 0), L"Set raw write mode."); COORD const coordZero = { 0 }; VERIFY_ARE_EQUAL(coordZero, csbiexBefore.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer."); DWORD dwWritten = 0; VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, strTest, cchTest, &dwWritten, nullptr), L"Write text into buffer using WriteFile"); VERIFY_ARE_EQUAL(cchTest, dwWritten); CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 }; csbiexAfter.cbSize = sizeof(csbiexAfter); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexAfter), L"Retrieve screen buffer properties after writing."); csbiexBefore.dwCursorPosition.X += (SHORT)cchTest; VERIFY_ARE_EQUAL(csbiexBefore.dwCursorPosition, csbiexAfter.dwCursorPosition, L"Verify cursor moved expected number of squares for the write length."); DWORD const cbReadBackBuffer = cchTest + 2; // +1 so we can read back a "space" that should be after what we wrote. +1 more so this can be null terminated for String class comparison. wistd::unique_ptr<char[]> strReadBack = wil::make_unique_failfast<char[]>(cbReadBackBuffer); ZeroMemory(strReadBack.get(), cbReadBackBuffer * sizeof(char)); DWORD dwRead = 0; VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterA(hOut, strReadBack.get(), cchTest + 1, coordZero, &dwRead), L"Read back the data in the buffer."); // +1 to read back the space that should be after the text we wrote strReadBackExpected += " "; // add in the space that should appear after the written text (buffer should be space filled when empty) VERIFY_ARE_EQUAL(strReadBackExpected, String(strReadBack.get()), L"Ensure that the buffer contents match what we expected based on what we wrote."); }
// BackupMetadataFile ReadAsync function with cancellation token canceled test // 1. Set up the expected values. // 2. ReadAsync call with cancellation token got canceled // 3. Verify it throws and the exception is as expected Awaitable<void> BackupMetadataFileTests::Test_BackupMetadataFile_ReadAsync_WithCanceledToken_Throws( __in KString const & fileName) { NTSTATUS status = STATUS_UNSUCCESSFUL; KAllocator & allocator = underlyingSystem_->PagedAllocator(); KWString filePath(allocator, fileName); BackupMetadataFile::SPtr backupMetadataFileSPtr = nullptr; status = BackupMetadataFile::Create( *prId_, filePath, allocator, backupMetadataFileSPtr); VERIFY_IS_TRUE(NT_SUCCESS(status)); // Expected const FABRIC_BACKUP_OPTION expectedBackupOption = FABRIC_BACKUP_OPTION_FULL; KGuid expectedParentBackupId; expectedParentBackupId.CreateNew(); KGuid expectedBackupId; expectedBackupId.CreateNew(); KGuid expectedPartitionId; expectedPartitionId.CreateNew(); const FABRIC_REPLICA_ID expectedReplicaId = 16; const LONG64 expectedDataLossNumber = 32; const LONG64 expectedConfigurationNumber = 64; TxnReplicator::Epoch expectedStartingEpoch = TxnReplicator::Epoch(expectedDataLossNumber, expectedConfigurationNumber); FABRIC_SEQUENCE_NUMBER expectedStartingLSN = 8; TxnReplicator::Epoch expectedBackupEpoch = TxnReplicator::Epoch(expectedDataLossNumber, expectedConfigurationNumber); FABRIC_SEQUENCE_NUMBER expectedBackupLSN = 128; status = co_await backupMetadataFileSPtr->WriteAsync( expectedBackupOption, expectedParentBackupId, expectedBackupId, expectedPartitionId, expectedReplicaId, expectedStartingEpoch, expectedStartingLSN, expectedBackupEpoch, expectedBackupLSN, CancellationToken::None); CODING_ERROR_ASSERT(NT_SUCCESS(status)); KGuid readId; readId.CreateNew(); CancellationTokenSource::SPtr cts; status = CancellationTokenSource::Create(allocator, BACKUPMETADATAFILETEST_TAG, cts); CODING_ERROR_ASSERT(NT_SUCCESS(status)); cts->Cancel(); status = co_await backupMetadataFileSPtr->ReadAsync(readId, cts->Token); VERIFY_ARE_EQUAL(STATUS_CANCELLED, status); Common::File::Delete(static_cast<LPCWSTR>(fileName), true); }
void CursorTests::TestGetSetConsoleCursorInfo() { DWORD dwSize; bool bVisible; VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"dwSize", dwSize), L"Get size parameter"); VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"bVisible", bVisible), L"Get visibility parameter"); // Get initial state of the cursor CONSOLE_CURSOR_INFO cciInitial = { 0 }; BOOL bResult = GetConsoleCursorInfo(Common::_hConsole, &cciInitial); VERIFY_WIN32_BOOL_SUCCEEDED(bResult, L"Retrieve initial cursor state."); // Fill a structure with the value under test CONSOLE_CURSOR_INFO cciTest = { 0 }; cciTest.bVisible = bVisible; cciTest.dwSize = dwSize; // If the cursor size is out of range, we expect a failure on set BOOL fExpectedResult = TRUE; if (cciTest.dwSize < 1 || cciTest.dwSize > 100) { fExpectedResult = FALSE; } // Attempt to set and verify that we get the expected result bResult = SetConsoleCursorInfo(Common::_hConsole, &cciTest); VERIFY_ARE_EQUAL(bResult, fExpectedResult, L"Ensure that return matches success/failure state we were expecting."); // Get the state of the cursor again CONSOLE_CURSOR_INFO cciReturned = { 0 }; bResult = GetConsoleCursorInfo(Common::_hConsole, &cciReturned); VERIFY_WIN32_BOOL_SUCCEEDED(bResult, L"GET back the cursor information we just set."); if (fExpectedResult) { // If we expected the set to be successful, the returned structure should match the test one VERIFY_ARE_EQUAL(cciReturned, cciTest, L"If we expected SET success, the values we set should match what we retrieved."); } else { // If we expected the set to fail, the returned structure should match the initial one VERIFY_ARE_EQUAL(cciReturned, cciInitial, L"If we expected SET failure, the initial values before the SET should match what we retrieved."); } }
// Helper function send a simple request to test the connection. // Take in the path to request and what path should be received in the server. void test_connection(test_http_server *p_server, http_client *p_client, const utility::string_t &request_path, const utility::string_t &expected_path) { p_server->next_request().then([expected_path](test_request *p_request) { http_asserts::assert_test_request_equals(p_request, methods::GET, expected_path); VERIFY_ARE_EQUAL(0u, p_request->reply(200)); }); http_asserts::assert_response_equals(p_client->request(methods::GET, request_path).get(), status_codes::OK); }
TEST_FIXTURE(e2e_raw_client, query_basic_properties_in_entity) { auto query_result = client.get_data_from_server(U("People(4)")).get(); VERIFY_ARE_EQUAL(query_result.size(), 1); VERIFY_ARE_EQUAL(edm_type_kind_t::Entity, query_result[0]->get_value_type()->get_type_kind()); std::shared_ptr<odata_entity_value> entity = std::dynamic_pointer_cast<odata_entity_value>(query_result[0]); //collection property std::shared_ptr<odata_value> collection_property; VERIFY_IS_TRUE(entity->get_property_value(U("Numbers"), collection_property)); VERIFY_ARE_EQUAL(edm_type_kind_t::Collection, collection_property->get_value_type()->get_type_kind()); auto collection_value = std::dynamic_pointer_cast<odata_collection_value>(collection_property); auto collection_vector = collection_value->get_collection_values(); VERIFY_ARE_EQUAL(3, collection_vector.size()); auto collectin_member = std::dynamic_pointer_cast<odata_primitive_value>(collection_vector[1]); VERIFY_ARE_EQUAL(U("555-555-5555"), collectin_member->as<::utility::string_t>()); //TODO-tiano: check the other property types }
void FileTests::TestReadFileBasicSync() { HANDLE const hIn = GetStdInputHandle(); VERIFY_IS_NOT_NULL(hIn, L"Verify we have the standard input handle."); DWORD dwMode = 0; VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hIn, dwMode), L"Set input mode for test."); VERIFY_WIN32_BOOL_SUCCEEDED(FlushConsoleInputBuffer(hIn), L"Flush input buffer in preparation for test."); char const chExpected = 'a'; Log::Comment(L"Send a key into the console."); SendFullKeyStrokeHelper(hIn, chExpected); char ch = '\0'; Log::Comment(L"Read with synchronous blocking read."); DWORD dwRead = 0; VERIFY_WIN32_BOOL_SUCCEEDED(ReadFile(hIn, &ch, 1, &dwRead, nullptr), L"Read file was successful."); VERIFY_ARE_EQUAL(1u, dwRead, L"Verify we read 1 character."); VERIFY_ARE_EQUAL(chExpected, ch); }
void test_server_utilities::verify_request( ::http::client::http_client *p_client, const utility::string_t &method, const utility::string_t &path, test_http_server *p_server, unsigned short code) { p_server->next_request().then([&](test_request *p_request) { http_asserts::assert_test_request_equals(p_request, method, path); VERIFY_ARE_EQUAL(0, p_request->reply(code)); }); http_asserts::assert_response_equals(p_client->request(method, path).get(), code); }
void FileTests::TestReadFileLineSync() { HANDLE const hIn = GetStdInputHandle(); VERIFY_IS_NOT_NULL(hIn, L"Verify we have the standard input handle."); DWORD dwMode = ENABLE_LINE_INPUT; VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hIn, dwMode), L"Set input mode for test."); VERIFY_WIN32_BOOL_SUCCEEDED(FlushConsoleInputBuffer(hIn), L"Flush input buffer in preparation for test."); char const chExpected = 'a'; Log::Comment(L"Send a key into the console followed by a carriage return."); SendFullKeyStrokeHelper(hIn, chExpected); SendFullKeyStrokeHelper(hIn, '\r'); char ch = '\0'; Log::Comment(L"Read back the input with a synchronous blocking read."); DWORD dwRead = 0; VERIFY_WIN32_BOOL_SUCCEEDED(ReadFile(hIn, &ch, 1, nullptr, nullptr), L"Read file was successful."); VERIFY_ARE_EQUAL(0u, dwRead, L"Verify we read 0 characters."); VERIFY_ARE_EQUAL(chExpected, ch); }
void ReadBackHelper(HANDLE hOut, COORD coordReadBackPos, DWORD dwReadBackLength, wistd::unique_ptr<char[]>& pszReadBack) { // Add one so it can be zero terminated. DWORD cbBuffer = dwReadBackLength + 1; wistd::unique_ptr<char[]> pszRead = wil::make_unique_failfast<char[]>(cbBuffer); ZeroMemory(pszRead.get(), cbBuffer * sizeof(char)); DWORD dwRead = 0; VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleOutputCharacterA(hOut, pszRead.get(), dwReadBackLength, coordReadBackPos, &dwRead), L"Read back data in the buffer."); VERIFY_ARE_EQUAL(dwReadBackLength, dwRead, L"Verify API reports we read back the number of characters we asked for."); pszReadBack.swap(pszRead); }
void WriteFileHelper(HANDLE hOut, CONSOLE_SCREEN_BUFFER_INFOEX& csbiexBefore, CONSOLE_SCREEN_BUFFER_INFOEX& csbiexAfter, PCSTR psTest, DWORD cchTest) { csbiexBefore.cbSize = sizeof(csbiexBefore); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexBefore), L"Retrieve screen buffer properties before writing."); DWORD dwWritten = 0; VERIFY_WIN32_BOOL_SUCCEEDED(WriteFile(hOut, psTest, cchTest, &dwWritten, nullptr), L"Write text into buffer using WriteFile"); VERIFY_ARE_EQUAL(cchTest, dwWritten, L"Verify all characters were written."); csbiexAfter.cbSize = sizeof(csbiexAfter); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexAfter), L"Retrieve screen buffer properties after writing."); }
void SendFullKeyStrokeHelper(HANDLE hIn, char ch) { INPUT_RECORD ir[2]; ZeroMemory(ir, ARRAYSIZE(ir) * sizeof(INPUT_RECORD)); ir[0].EventType = KEY_EVENT; ir[0].Event.KeyEvent.bKeyDown = TRUE; ir[0].Event.KeyEvent.dwControlKeyState = ch < 0x20 ? LEFT_CTRL_PRESSED : 0; // set left_ctrl_pressed for control keys. ir[0].Event.KeyEvent.uChar.AsciiChar = ch; ir[0].Event.KeyEvent.wVirtualKeyCode = VkKeyScanA(ir[0].Event.KeyEvent.uChar.AsciiChar); ir[0].Event.KeyEvent.wVirtualScanCode = (WORD)MapVirtualKeyA(ir[0].Event.KeyEvent.wVirtualKeyCode, MAPVK_VK_TO_VSC); ir[0].Event.KeyEvent.wRepeatCount = 1; ir[1] = ir[0]; ir[1].Event.KeyEvent.bKeyDown = FALSE; DWORD dwWritten = 0; VERIFY_WIN32_BOOL_SUCCEEDED(WriteConsoleInputA(hIn, ir, (DWORD)ARRAYSIZE(ir), &dwWritten), L"Writing key stroke."); VERIFY_ARE_EQUAL((DWORD)ARRAYSIZE(ir), dwWritten, L"Written matches expected."); }
shared_ptr<FailoverManagerStore> FailoverManagerStoreTest::InitializeStore( wstring ownerId, bool shouldPass, bool existingStore, Common::Guid const & partitionId, ::FABRIC_REPLICA_ID replicaId, Common::ComponentRoot const & root, const wstring storeType) { UNREFERENCED_PARAMETER(ownerId); UNREFERENCED_PARAMETER(shouldPass); if (storeType == L"ESENT") { auto replicatedStore = Store::KeyValueStoreReplica::CreateForUnitTests( partitionId, replicaId, Store::EseLocalStoreSettings(GetEseFilename(), GetEseDirectory()), root); ErrorCode error = replicatedStore->InitializeLocalStoreForUnittests(existingStore); shared_ptr<FailoverManagerStore> store = make_shared<FailoverManagerStore>(move(replicatedStore)); if (shouldPass) { VERIFY_ARE_EQUAL(ErrorCodeValue::Success, error.ReadValue(), L"store.Open did not return success"); return store; } else { VERIFY_ARE_NOT_EQUAL(ErrorCodeValue::Success, error.ReadValue(), L"store.Open returned success"); return nullptr; } } Common::Assert::CodingError("StoreType not found in properties"); }
void FileTests::TestReadFileLine() { HANDLE const hIn = GetStdInputHandle(); VERIFY_IS_NOT_NULL(hIn, L"Verify we have the standard input handle."); DWORD dwMode = ENABLE_LINE_INPUT; VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hIn, dwMode), L"Set input mode for test."); VERIFY_WIN32_BOOL_SUCCEEDED(FlushConsoleInputBuffer(hIn), L"Flush input buffer in preparation for test."); char ch = '\0'; Log::Comment(L"Queue background blocking read file operation."); auto BackgroundRead = std::async([&] { DWORD dwRead = 0; VERIFY_WIN32_BOOL_SUCCEEDED(ReadFile(hIn, &ch, 1, &dwRead, nullptr), L"Read file was successful."); VERIFY_ARE_EQUAL(1u, dwRead, L"Verify we read 1 character."); }); char const chExpected = 'a'; Log::Comment(L"Send a key into the console."); SendFullKeyStrokeHelper(hIn, chExpected); auto status = BackgroundRead.wait_for(std::chrono::milliseconds(250)); VERIFY_ARE_EQUAL(std::future_status::timeout, status, L"We should still be waiting for a result."); VERIFY_ARE_EQUAL('\0', ch, L"Character shouldn't be filled by background read yet."); Log::Comment(L"Send a line feed character, we should stay blocked."); SendFullKeyStrokeHelper(hIn, '\n'); status = BackgroundRead.wait_for(std::chrono::milliseconds(250)); VERIFY_ARE_EQUAL(std::future_status::timeout, status, L"We should still be waiting for a result."); VERIFY_ARE_EQUAL('\0', ch, L"Character shouldn't be filled by background read yet."); Log::Comment(L"Now send a carriage return into the console to signify the end of the input line."); SendFullKeyStrokeHelper(hIn, '\r'); Log::Comment(L"Wait for background thread to unblock."); BackgroundRead.wait(); VERIFY_ARE_EQUAL(chExpected, ch); }
Awaitable<void> ReplicatorPerfTest::Run( __in wstring const & testFolder, __in int concurrentTransactions, __in int totalTransactions, __in Data::Log::LogManager & logManager) { #ifndef PERF_TEST UNREFERENCED_PARAMETER(testFolder); UNREFERENCED_PARAMETER(concurrentTransactions); UNREFERENCED_PARAMETER(totalTransactions); UNREFERENCED_PARAMETER(logManager); #else Replica::SPtr replica = Replica::Create( pId_, rId_, testFolder, logManager, underlyingSystem_->PagedAllocator()); co_await replica->OpenAsync(); FABRIC_EPOCH epoch1; epoch1.DataLossNumber = 1; epoch1.ConfigurationNumber = 1; epoch1.Reserved = nullptr; co_await replica->ChangeRoleAsync(epoch1, FABRIC_REPLICA_ROLE_PRIMARY); replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED); replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED); KUri::CSPtr stateProviderName = GetStateProviderName(0); { Transaction::SPtr txn; replica->TxnReplicator->CreateTransaction(txn); KFinally([&] {txn->Dispose(); }); NTSTATUS status = co_await replica->TxnReplicator->AddAsync(*txn, *stateProviderName, L"ReplicatorPerfTest"); VERIFY_IS_TRUE(NT_SUCCESS(status)); co_await txn->CommitAsync(); } { IStateProvider2::SPtr stateProvider2; NTSTATUS status = replica->TxnReplicator->Get(*stateProviderName, stateProvider2); VERIFY_IS_TRUE(NT_SUCCESS(status)); VERIFY_IS_NOT_NULL(stateProvider2); VERIFY_ARE_EQUAL(*stateProviderName, stateProvider2->GetName()); IStore<int, int>::SPtr store = dynamic_cast<IStore<int, int>*>(stateProvider2.RawPtr()); Stopwatch s; s.Start(); KArray<Awaitable<void>> tasks(underlyingSystem_->PagedAllocator(), concurrentTransactions, 0); for (int i = 0; i < concurrentTransactions; i++) { status = tasks.Append(DoWorkOnKey(store, replica, totalTransactions / concurrentTransactions, i)); KInvariant(NT_SUCCESS(status)); } co_await TaskUtilities<Awaitable<void>>::WhenAll(tasks); s.Stop(); int64 txPerSec = ((totalTransactions * 1000) / s.ElapsedMilliseconds); Trace.WriteInfo( TraceComponent, "{0}: Tx/Sec is {1}", prId_->TraceId, txPerSec); } replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY); replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY); co_await replica->CloseAsync(); #endif co_return; }
void FileTests::TestWriteFileProcessed() { // \x7 is bell // \x8 is backspace // \x9 is tab // \xa is linefeed // \xd is carriage return // All should cause activity in processed mode. HANDLE const hOut = GetStdOutputHandle(); VERIFY_IS_NOT_NULL(hOut, L"Verify we have the standard output handle."); CONSOLE_SCREEN_BUFFER_INFOEX csbiexOriginal = { 0 }; csbiexOriginal.cbSize = sizeof(csbiexOriginal); VERIFY_WIN32_BOOL_SUCCEEDED(GetConsoleScreenBufferInfoEx(hOut, &csbiexOriginal), L"Retrieve screen buffer properties at beginning of test."); VERIFY_WIN32_BOOL_SUCCEEDED(SetConsoleMode(hOut, ENABLE_PROCESSED_OUTPUT), L"Set processed write mode."); COORD const coordZero = { 0 }; VERIFY_ARE_EQUAL(coordZero, csbiexOriginal.dwCursorPosition, L"Cursor should be at 0,0 in fresh buffer."); // Declare variables needed for each character test. CONSOLE_SCREEN_BUFFER_INFOEX csbiexBefore = { 0 }; CONSOLE_SCREEN_BUFFER_INFOEX csbiexAfter = { 0 }; COORD coordExpected = { 0 }; PCSTR pszTest; DWORD cchTest; PCSTR pszReadBackExpected; DWORD cchReadBack; wistd::unique_ptr<char[]> pszReadBack; // 1. Test bell (\x7) { pszTest = "z\x7"; cchTest = (DWORD)strlen(pszTest); pszReadBackExpected = "z "; cchReadBack = (DWORD)strlen(pszReadBackExpected); // Write z and a bell. Cursor should move once as bell should have made audible noise (can't really test) and not moved or printed anything. WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest); coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X += 1; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved once for printable character and not for bell."); // Read back written data. ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack); VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer."); } // 2. Test backspace (\x8) { pszTest = "yx\x8"; cchTest = (DWORD)strlen(pszTest); pszReadBackExpected = "yx "; cchReadBack = (DWORD)strlen(pszReadBackExpected); // Write two characters and a backspace. Cursor should move only one forward as the backspace should have moved the cursor back one after printing the second character. // The backspace character itself is typically non-destructive so it should only affect the cursor, not the buffer contents. WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest); coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X += 1; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved twice forward for printable characters and once backward for backspace."); // Read back written data. ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack); VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer."); } // 3. Test tab (\x9) { // The tab character will space pad out the buffer to the next multiple-of-8 boundary. // NOTE: This is dependent on the previous tests running first. pszTest = "\x9"; cchTest = (DWORD)strlen(pszTest); pszReadBackExpected = " "; cchReadBack = (DWORD)strlen(pszReadBackExpected); // Write tab character. Cursor should move out to the next multiple-of-8 and leave space characters in its wake. WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest); coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X = 8; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved forward to position 8 for tab."); // Read back written data. ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack); VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer."); } // 4. Test linefeed (\xa) { // The line feed character should move us down to the next line. pszTest = "\xaQ"; cchTest = (DWORD)strlen(pszTest); pszReadBackExpected = "Q "; cchReadBack = (DWORD)strlen(pszReadBackExpected); // Write line feed character. Cursor should move down a line and then the Q from our string should be printed. WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest); coordExpected.X = 1; coordExpected.Y = 1; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved down a line and then one character over for linefeed + Q."); // Read back written data from the 2nd line. COORD coordRead; coordRead.Y = 1; coordRead.X = 0; ReadBackHelper(hOut, coordRead, cchReadBack, pszReadBack); VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer."); } // 5. Test carriage return (\xd) { // The carriage return character should move us to the front of the line. pszTest = "J\xd"; cchTest = (DWORD)strlen(pszTest); pszReadBackExpected = "QJ "; // J written, then move to beginning of line. cchReadBack = (DWORD)strlen(pszReadBackExpected); // Write text and carriage return character. Cursor should end up at the beginning of this line. The J should have been printed in the line before we moved. WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest); coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X = 0; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved to beginning of line for carriage return character."); // Read back text written from the 2nd line. ReadBackHelper(hOut, csbiexAfter.dwCursorPosition, cchReadBack, pszReadBack); VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer."); } // 6. Print a character over the top of the existing { // After the carriage return, try typing on top of the Q with a K pszTest = "K"; cchTest = (DWORD)strlen(pszTest); pszReadBackExpected = "KJ "; // NOTE: This is based on the previous test(s). cchReadBack = (DWORD)strlen(pszReadBackExpected); // Write text. Cursor should end up on top of the J. WriteFileHelper(hOut, csbiexBefore, csbiexAfter, pszTest, cchTest); coordExpected = csbiexBefore.dwCursorPosition; coordExpected.X += 1; VERIFY_ARE_EQUAL(coordExpected, csbiexAfter.dwCursorPosition, L"Verify cursor moved over one for printing character."); // Read back text written from the 2nd line. ReadBackHelper(hOut, csbiexBefore.dwCursorPosition, cchReadBack, pszReadBack); VERIFY_ARE_EQUAL(String(pszReadBackExpected), String(pszReadBack.get()), L"Verify text matches what we expected to be written into the buffer."); } }
void FontTests::TestFontScenario() { const HANDLE hConsoleOutput = GetStdOutputHandle(); Log::Comment(L"1. Ensure that the various GET APIs for font information align with each other."); CONSOLE_FONT_INFOEX cfie = {0}; cfie.cbSize = sizeof(cfie); VERIFY_WIN32_BOOL_SUCCEEDED(OneCoreDelay::GetCurrentConsoleFontEx(hConsoleOutput, FALSE, &cfie)); CONSOLE_FONT_INFO cfi = {0}; VERIFY_WIN32_BOOL_SUCCEEDED(OneCoreDelay::GetCurrentConsoleFont(hConsoleOutput, FALSE, &cfi)); VERIFY_ARE_EQUAL(cfi.nFont, cfie.nFont, L"Ensure regular and Ex APIs return same nFont"); VERIFY_ARE_NOT_EQUAL(cfi.dwFontSize, c_coordZero, L"Ensure non-zero font size"); VERIFY_ARE_EQUAL(cfi.dwFontSize, cfie.dwFontSize, L"Ensure regular and Ex APIs return same dwFontSize"); const COORD coordCurrentFontSize = OneCoreDelay::GetConsoleFontSize(hConsoleOutput, cfi.nFont); VERIFY_ARE_EQUAL(coordCurrentFontSize, cfi.dwFontSize, L"Ensure GetConsoleFontSize output matches GetCurrentConsoleFont"); // --------------------- Log::Comment(L"2. Ensure that our font settings round-trip appropriately through the Ex APIs"); CONSOLE_FONT_INFOEX cfieSet = {0}; cfieSet.cbSize = sizeof(cfieSet); cfieSet.dwFontSize.Y = 12; VERIFY_SUCCEEDED(StringCchCopy(cfieSet.FaceName, ARRAYSIZE(cfieSet.FaceName), L"Lucida Console")); VERIFY_WIN32_BOOL_SUCCEEDED(OneCoreDelay::SetCurrentConsoleFontEx(hConsoleOutput, FALSE, &cfieSet)); CONSOLE_FONT_INFOEX cfiePost = {0}; cfiePost.cbSize = sizeof(cfiePost); VERIFY_WIN32_BOOL_SUCCEEDED(OneCoreDelay::GetCurrentConsoleFontEx(hConsoleOutput, FALSE, &cfiePost)); // Ensure that the two values we attempted to set did accurately round-trip through the API. // The other unspecified values may have been adjusted/updated by GDI. if (0 != NoThrowString(cfieSet.FaceName).CompareNoCase(cfiePost.FaceName)) { Log::Comment(L"We cannot test changing fonts on systems that do not have alternatives available. Skipping test."); Log::Result(WEX::Logging::TestResults::Result::Skipped); return; } VERIFY_ARE_EQUAL(cfieSet.dwFontSize.Y, cfiePost.dwFontSize.Y); // Ensure that the entire structure we received matches what we expect to usually get for this Lucida Console Size 12 ask. CONSOLE_FONT_INFOEX cfieFullExpected = { 0 }; cfieFullExpected.cbSize = sizeof(cfieFullExpected); wcscpy_s(cfieFullExpected.FaceName, L"Lucida Console"); if (!OneCoreDelay::IsIsWindowPresent()) { // On OneCore Windows without GDI, this is what we expect to get. cfieFullExpected.dwFontSize.X = 8; cfieFullExpected.dwFontSize.Y = 12; cfieFullExpected.FontFamily = 4; cfieFullExpected.FontWeight = 0; } else { // On client Windows with GDI, this is what we expect to get. cfieFullExpected.dwFontSize.X = 7; cfieFullExpected.dwFontSize.Y = 12; cfieFullExpected.FontFamily = 54; cfieFullExpected.FontWeight = 400; } VERIFY_ARE_EQUAL(cfieFullExpected, cfiePost); }
void TestGetConsoleAliasHelper(TCH* ptszSourceGiven, TCH* ptszExpectedTargetGiven, TCH* ptszExeNameGiven, DWORD& dwSource, DWORD& dwTarget, DWORD& dwExeName, bool& /*bUnicode*/, bool& bSetFirst) { TCH* ptszSource = nullptr; TCH* ptszExeName = nullptr; TCH* ptszExpectedTarget = ptszExpectedTargetGiven; TCH* ptchTargetBuffer = nullptr; DWORD cbTargetBuffer = 0; switch (dwSource) { case 0: ptszSource = nullptr; Log::Comment(L"Using null source arg."); break; case 1: ptszSource = ptszSourceGiven; Log::Comment(String().Format(L"Using source arg: '" TSTRFORMAT "'", ptszSource)); break; default: VERIFY_FAIL(L"Unknown type."); } switch (dwExeName) { case 0: ptszExeName = nullptr; Log::Comment(L"Using null exe name."); break; case 1: ptszExeName = ptszExeNameGiven; Log::Comment(String().Format(L"Using exe name arg: '" TSTRFORMAT "'", ptszExeName)); break; default: VERIFY_FAIL(L"Unknown type."); } DWORD const cbExpectedTargetString = (DWORD)TLEN(ptszExpectedTargetGiven) * sizeof(TCH); switch (dwTarget) { case 0: cbTargetBuffer = 0; break; case 1: cbTargetBuffer = sizeof(TCH); break; case 2: cbTargetBuffer = cbExpectedTargetString - sizeof(TCH); break; case 3: cbTargetBuffer = cbExpectedTargetString; break; case 4: cbTargetBuffer = cbExpectedTargetString + sizeof(TCH); break; case 5: cbTargetBuffer = cbExpectedTargetString + sizeof(TCH) + sizeof(TCH); break; case 6: cbTargetBuffer = MAX_PATH * sizeof(TCH); break; default: VERIFY_FAIL(L"Unknown type."); } if (cbTargetBuffer == 0) { ptchTargetBuffer = nullptr; } else { ptchTargetBuffer = new TCH[cbTargetBuffer / sizeof(TCH)]; ZeroMemory(ptchTargetBuffer, cbTargetBuffer); } auto freeTargetBuffer = wil::scope_exit([&]() { if (ptchTargetBuffer != nullptr) { delete[] ptchTargetBuffer; } }); Log::Comment(String().Format(L"Using target buffer size: '%d'", cbTargetBuffer)); // Set the alias if we're supposed to and prepare for cleanup later. if (bSetFirst) { AddConsoleAliasT(ptszSource, ptszExpectedTarget, ptszExeName); } // This is strange because it's a scope exit so we need to declare in the parent scope, then let it go if we didn't actually need it. // I just prefer keeping the exit next to the allocation so it doesn't get lost. auto removeAliasOnExit = wil::scope_exit([&] { AddConsoleAliasT(ptszSource, NULL, ptszExeName); }); if (!bSetFirst) { removeAliasOnExit.release(); } // Determine what the result codes should be // See console client side in conlibk... // a->TargetLength on the server side will become the return value // The returned status will be put into SetLastError // If there is an error and it's not STATUS_BUFFER_TOO_SMALL, then a->TargetLength (and the return) will be zeroed. // Some sample errors: // - 87 = 0x57 = ERROR_INVALID_PARAMETER // - 122 = 0x7a = ERROR_INSUFFICIENT_BUFFER DWORD dwExpectedResult; DWORD dwExpectedLastError; // NOTE: This order is important. Don't rearrange IF statements. if (nullptr == ptszSource || nullptr == ptszExeName) { // If the source or exe name aren't valid, invalid parameter. dwExpectedResult = 0; dwExpectedLastError = ERROR_INVALID_PARAMETER; } else if (!bSetFirst) { // If we didn't set an alias, generic failure. dwExpectedResult = 0; dwExpectedLastError = ERROR_GEN_FAILURE; } else if (ptchTargetBuffer == nullptr || cbTargetBuffer < (cbExpectedTargetString + sizeof(TCH))) // expected target plus a null terminator. { // If the target isn't enough space, insufficient buffer. dwExpectedResult = cbTargetBuffer; // For some reason, the console API *ALWAYS* says it needs enough space as if we were copying Unicode, // even if the final result will be ANSI. // Therefore, if we're mathing based on a char size buffer, multiple the expected result by 2. #pragma warning(suppress:4127) // This is a constant, but conditionally compiled twice so we need the check. if (1 == sizeof(TCH)) { dwExpectedResult *= sizeof(wchar_t); } dwExpectedLastError = ERROR_INSUFFICIENT_BUFFER; } else { // Otherwise, success. API should always null terminate string. dwExpectedResult = cbExpectedTargetString + sizeof(TCH); // expected target plus a null terminator. dwExpectedLastError = 0; } TCH* ptchExpectedTarget; auto freeExpectedTarget = wil::scope_exit([&] { if (ptchExpectedTarget != nullptr) { delete[] ptchExpectedTarget; ptchExpectedTarget = nullptr; } }); if (0 == cbTargetBuffer) { // If no buffer, we should expect null back out. ptchExpectedTarget = nullptr; } else { // If there is buffer space, allocate it. ptchExpectedTarget = new TCH[cbTargetBuffer / sizeof(TCH)]; ZeroMemory(ptchExpectedTarget, cbTargetBuffer); } if (0 == dwExpectedLastError) { // If it was successful, it should have been filled. Otherwise it will be zeroed as when it started. StringCbCopyT(ptchExpectedTarget, cbTargetBuffer, ptszExpectedTargetGiven); } // Perform the test SetLastError(S_OK); DWORD const dwActualResult = GetConsoleAliasT(ptszSource, ptchTargetBuffer, cbTargetBuffer, ptszExeName); DWORD const dwActualLastError = GetLastError(); VERIFY_ARE_EQUAL(dwExpectedResult, dwActualResult, L"Ensure result code/return value matches expected."); VERIFY_ARE_EQUAL(dwExpectedLastError, dwActualLastError, L"Ensure last error code matches expected."); Log::Comment(L"Compare target buffer character by character..."); for (size_t i = 0; i < (cbTargetBuffer / sizeof(TCH)); i++) { if (ptchExpectedTarget[i] != ptchTargetBuffer[i]) { VERIFY_FAIL(String().Format(L"Target mismatch at %d. Expected: '" TCHFORMAT "' Actual: '" TCHFORMAT "'", i, ptchExpectedTarget[i], ptchTargetBuffer[i])); } } }