main.cpp (4816B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include <AppInstallerLogging.h> 5 #include <AppInstallerFileLogger.h> 6 #include <Public/AppInstallerTelemetry.h> 7 #include <Telemetry/TraceLogging.h> 8 #include "TestCommon.h" 9 #include "TestSettings.h" 10 11 using namespace winrt; 12 using namespace winrt::Windows::Foundation; 13 using namespace std::string_literals; 14 using namespace AppInstaller; 15 16 17 // Logs the AppInstaller log target to break up individual tests 18 struct LoggingBreakListener : public Catch::EventListenerBase 19 { 20 using EventListenerBase::EventListenerBase; 21 22 void testCaseStarting(const Catch::TestCaseInfo& info) override 23 { 24 Catch::EventListenerBase::testCaseStarting(info); 25 AICLI_LOG(Test, Info, << "========== Test Case Begins :: " << info.name << " =========="); 26 TestCommon::TempFile::SetTestFailed(false); 27 } 28 29 void testCaseEnded(const Catch::TestCaseStats& testCaseStats) override 30 { 31 AICLI_LOG(Test, Info, << "========== Test Case Ends =========="); 32 if (!testCaseStats.totals.delta(lastTotals).testCases.allOk()) 33 { 34 TestCommon::TempFile::SetTestFailed(true); 35 } 36 lastTotals = testCaseStats.totals; 37 Catch::EventListenerBase::testCaseEnded(testCaseStats); 38 } 39 40 Catch::Totals lastTotals{}; 41 }; 42 CATCH_REGISTER_LISTENER(LoggingBreakListener); 43 44 // Map CATCH exceptions so that WIL doesn't fail fast the tests 45 HRESULT __stdcall CatchResultFromCaughtException() WI_PFN_NOEXCEPT 46 { 47 try 48 { 49 throw; 50 } 51 catch (const Catch::TestFailureException&) 52 { 53 // REC_E_TEST_FAILURE :: Test failure. 54 // Not sure what could generate this, but it is unlikely that we use it. 55 // Since the message is aligned with the issue it should help diagnosis. 56 return 0x8b051032; 57 } 58 catch (...) 59 { 60 // Means we couldn't map the exception 61 return S_OK; 62 } 63 } 64 65 int main(int argc, char** argv) 66 { 67 init_apartment(); 68 69 bool hasSetTestDataBasePath = false; 70 bool waitBeforeReturn = false; 71 bool keepSQLLogging = false; 72 73 std::vector<char*> args; 74 for (int i = 0; i < argc; ++i) 75 { 76 if ("-ktf"s == argv[i]) 77 { 78 TestCommon::TempFile::SetDestructorBehavior(TestCommon::TempFileDestructionBehavior::Keep); 79 } 80 else if ("-seof"s == argv[i]) 81 { 82 TestCommon::TempFile::SetDestructorBehavior(TestCommon::TempFileDestructionBehavior::ShellExecuteOnFailure); 83 } 84 else if ("-log"s == argv[i]) 85 { 86 Logging::FileLogger::Add(); 87 } 88 else if ("-logto"s == argv[i]) 89 { 90 ++i; 91 Logging::FileLogger::Add(std::filesystem::path{ argv[i] }); 92 } 93 else if ("-tdd"s == argv[i]) 94 { 95 ++i; 96 if (i < argc) 97 { 98 TestCommon::TestDataFile::SetTestDataBasePath(argv[i]); 99 hasSetTestDataBasePath = true; 100 } 101 } 102 else if ("-wait"s == argv[i]) 103 { 104 waitBeforeReturn = true; 105 } 106 else if ("-logsql"s == argv[i]) 107 { 108 keepSQLLogging = true; 109 } 110 else 111 { 112 args.push_back(argv[i]); 113 } 114 } 115 116 // If not set, use the current executables path 117 if (!hasSetTestDataBasePath) 118 { 119 wchar_t fullFileName[1024]; 120 DWORD chars = ARRAYSIZE(fullFileName); 121 if (QueryFullProcessImageNameW(GetCurrentProcess(), 0, fullFileName, &chars)) 122 { 123 std::filesystem::path filepath{ fullFileName }; 124 filepath.remove_filename(); 125 TestCommon::TestDataFile::SetTestDataBasePath(filepath); 126 } 127 } 128 129 // Enable logging, to force log string building to run. 130 // Disable SQL by default, as it generates 10s of MBs of log file and 131 // increases the full test run time by 60% or more. 132 // By not creating a log target, it will all be thrown away. 133 Logging::Log().SetEnabledChannels(Logging::Channel::All); 134 if (!keepSQLLogging) 135 { 136 Logging::Log().DisableChannel(Logging::Channel::SQL); 137 } 138 Logging::Log().SetLevel(Logging::Level::Verbose); 139 Logging::EnableWilFailureTelemetry(); 140 141 wil::SetResultFromCaughtExceptionCallback(CatchResultFromCaughtException); 142 143 // Forcibly enable event writing to catch bugs in that code 144 g_IsTelemetryProviderEnabled = true; 145 146 TestCommon::SetTestPathOverrides(); 147 148 // Remove any existing settings files in the new tests path 149 TestCommon::UserSettingsFileGuard settingsGuard; 150 151 int result = Catch::Session().run(static_cast<int>(args.size()), args.data()); 152 153 if (waitBeforeReturn) 154 { 155 // Wait for some input before returning 156 std::cin.get(); 157 } 158 159 return result; 160 }