master
cpp 134 lines 4.83 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 WSLCE2ESessionEnterTests.cpp
8
9 Abstract:
10
11 This file contains end-to-end tests for the wslc session enter command.
12 --*/
13
14 #include "precomp.h"
15 #include "windows/Common.h"
16 #include "WSLCCLITestHelpers.h"
17 #include "WSLCExecutor.h"
18 #include "WSLCE2EHelpers.h"
19 #include "WSLCSessionDefaults.h"
20 #include "WSLCUserSettings.h"
21
22 using namespace WEX::Logging;
23
24 namespace WSLCE2ETests {
25
26 namespace {
27
28 const std::filesystem::path& GetDefaultStoragePath()
29 {
30 auto isElevated = wsl::windows::common::security::IsTokenElevated(wil::open_current_access_token(TOKEN_QUERY).get());
31
32 static const std::filesystem::path basePath =
33 wsl::windows::common::filesystem::GetLocalAppDataPath(nullptr) / wsl::windows::wslc::DefaultStorageSubPath;
34
35 // Session names are now qualified with the username (e.g. "wslc-cli-alice").
36 wchar_t username[256 + 1] = {};
37 DWORD usernameLen = ARRAYSIZE(username);
38 THROW_IF_WIN32_BOOL_FALSE(GetUserNameW(username, &usernameLen));
39
40 auto adminName = std::format(L"{}-{}", wsl::windows::wslc::DefaultAdminSessionName, username);
41 auto nonAdminName = std::format(L"{}-{}", wsl::windows::wslc::DefaultSessionName, username);
42
43 static const std::filesystem::path storagePathNonAdmin = basePath / nonAdminName;
44 static const std::filesystem::path storagePathAdmin = basePath / adminName;
45
46 return isElevated ? storagePathAdmin : storagePathNonAdmin;
47 }
48
49 } // namespace
50
51 class WSLCE2ESessionEnterTests
52 {
53 WSLC_TEST_CLASS(WSLCE2ESessionEnterTests)
54
55 TEST_CLASS_SETUP(TestClassSetup)
56 {
57 // Ensure that the wslc cli session storage is created.
58 RunWslc(L"image ls").Verify({.ExitCode = 0});
59
60 // Terminate the wslc session since we use its storage path in this test class.
61 RunWslc(L"system session terminate");
62 return true;
63 }
64
65 WSLC_TEST_METHOD(WSLCE2E_SessionEnter_WithName)
66 {
67 constexpr auto sessionName = L"test-wslc-session-enter";
68
69 // Run an interactive session enter with an explicit name.
70 auto session = RunWslcInteractive(std::format(L"system session enter \"{}\" --name {}", GetDefaultStoragePath(), sessionName));
71 VERIFY_IS_TRUE(session.IsRunning(), L"Session should be running");
72
73 session.ExpectStdout(VT::SESSION_PROMPT);
74
75 // Validate that the shell is running as root.
76 session.WriteLine("whoami");
77 session.ExpectStdout(VT::RESET);
78 session.ExpectCommandEcho("whoami");
79 session.ExpectStdout("root\r\n");
80 session.ExpectStdout(VT::SESSION_PROMPT);
81
82 // Verify the session appears in session list.
83 auto listResult = RunWslc(L"system session list");
84 listResult.Verify({.Stderr = L"", .ExitCode = S_OK});
85 VERIFY_IS_TRUE(listResult.Stdout.has_value());
86 VERIFY_IS_TRUE(listResult.Stdout->find(sessionName) != std::wstring::npos);
87
88 // Exit the shell.
89 VERIFY_ARE_EQUAL(session.Exit(), 0);
90
91 // Verify the session is no longer in the session list after exiting.
92 listResult = RunWslc(L"system session list");
93 listResult.Verify({.Stderr = L"", .ExitCode = S_OK});
94 VERIFY_IS_TRUE(listResult.Stdout.has_value());
95 VERIFY_IS_FALSE(listResult.Stdout->find(sessionName) != std::wstring::npos);
96 }
97
98 WSLC_TEST_METHOD(WSLCE2E_SessionEnter_WithoutName_GeneratesGuid)
99 {
100 auto session = RunWslcInteractive(std::format(L"system session enter \"{}\"", GetDefaultStoragePath()));
101 VERIFY_IS_TRUE(session.IsRunning(), L"Session should be running");
102
103 session.ExpectStderr("Created session: ");
104 session.ExpectStdout(VT::SESSION_PROMPT);
105
106 VERIFY_ARE_EQUAL(session.Exit(), 0);
107 }
108
109 WSLC_TEST_METHOD(WSLCE2E_SessionEnter_StoragePathNotFound)
110 {
111 auto result = RunWslc(L"system session enter does-not-exist");
112
113 // The CLI resolves the storage argument to an absolute path (see EnterSession task) and the
114 // service validates it eagerly at session creation, reporting the friendly "No WSLC session
115 // found in '<path>'" message rather than a bare system error.
116 const auto storagePath = std::filesystem::absolute(L"does-not-exist").wstring();
117 result.Verify({
118 .Stderr = FormatErrorMessage(
119 wsl::shared::Localization::MessageWslcSessionStorageNotFound(storagePath), L"ERROR_PATH_NOT_FOUND"),
120 .ExitCode = 1,
121 });
122 }
123
124 WSLC_TEST_METHOD(WSLCE2E_Help_ExecutionErrorDoesNotShowHelp)
125 {
126 const auto result = RunWslc(L"--session unsupported system session enter ignored");
127 result.Verify({
128 .Stdout = L"",
129 .Stderr = wsl::shared::Localization::MessageWslcSessionOptionNotSupported() + L"\r\n",
130 .ExitCode = 1,
131 });
132 }
133 };
134 } // namespace WSLCE2ETests