CLI: Add logging options with end-to-end tests#40314
CLI: Add logging options with end-to-end tests#40314AmelBawa-msft wants to merge 3 commits intofeature/wsl-for-appsfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds additional wslc container logs CLI options (tail/since/until/timestamps) and introduces an end-to-end test suite to validate the container logs command behavior.
Changes:
- Extend
container logsargument set to include--tail,--since,--until, and--timestamps. - Plumb the new options through task/service layers to the COM
IWSLCContainer::Logs(...)call. - Add new E2E tests for
container logshelp/success plus--tail,--timestamps, and--follow, and add localization strings for the new args.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/windows/wslc/e2e/WSLCE2EContainerLogsTests.cpp | New E2E coverage for wslc container logs behaviors and selected options. |
| src/windows/wslc/tasks/ContainerTasks.cpp | Parse logs options from CLI args and pass them down to the service layer. |
| src/windows/wslc/services/ContainerService.h | Extend ContainerService::Logs API surface to accept new log options. |
| src/windows/wslc/services/ContainerService.cpp | Forward flags and since/until/tail parameters to IWSLCContainer::Logs. |
| src/windows/wslc/commands/ContainerLogsCommand.cpp | Register new arguments for the container logs command. |
| src/windows/wslc/arguments/ArgumentDefinitions.h | Define new arg types (Since, Until, Tail, Timestamps) for the CLI framework. |
| localization/strings/en-US/Resources.resw | Add localized descriptions for the new CLI arguments. |
| tail = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Tail>())); | ||
| } | ||
|
|
||
| ULONGLONG since = 0; | ||
| if (context.Args.Contains(ArgType::Since)) | ||
| { | ||
| since = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Since>())); | ||
| } | ||
|
|
||
| ULONGLONG until = 0; | ||
| if (context.Args.Contains(ArgType::Until)) | ||
| { | ||
| until = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Until>())); |
There was a problem hiding this comment.
Parsing --tail with std::stoull can throw std::invalid_argument/std::out_of_range, which will bypass the command argument error path and end up as a generic caught exception. Use the existing argument validation helpers (e.g., validation::GetIntegerFromString<ULONGLONG>(..., L"tail")) or convert failures into an ArgumentException so users get a clear, consistent CLI error for invalid values.
| tail = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Tail>())); | |
| } | |
| ULONGLONG since = 0; | |
| if (context.Args.Contains(ArgType::Since)) | |
| { | |
| since = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Since>())); | |
| } | |
| ULONGLONG until = 0; | |
| if (context.Args.Contains(ArgType::Until)) | |
| { | |
| until = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Until>())); | |
| tail = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Tail>(), L"tail"); | |
| } | |
| ULONGLONG since = 0; | |
| if (context.Args.Contains(ArgType::Since)) | |
| { | |
| since = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Since>(), L"since"); | |
| } | |
| ULONGLONG until = 0; | |
| if (context.Args.Contains(ArgType::Until)) | |
| { | |
| until = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Until>(), L"until"); |
| tail = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Tail>())); | ||
| } | ||
|
|
||
| ULONGLONG since = 0; | ||
| if (context.Args.Contains(ArgType::Since)) | ||
| { | ||
| since = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Since>())); | ||
| } | ||
|
|
||
| ULONGLONG until = 0; | ||
| if (context.Args.Contains(ArgType::Until)) | ||
| { | ||
| until = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Until>())); |
There was a problem hiding this comment.
--since is parsed with std::stoull, which can throw and produce a non-user-friendly error path. Prefer validation::GetIntegerFromString<ULONGLONG> (or a dedicated validator in Argument::Validate) so invalid timestamps are rejected with a consistent CLI ArgumentException message.
| tail = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Tail>())); | |
| } | |
| ULONGLONG since = 0; | |
| if (context.Args.Contains(ArgType::Since)) | |
| { | |
| since = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Since>())); | |
| } | |
| ULONGLONG until = 0; | |
| if (context.Args.Contains(ArgType::Until)) | |
| { | |
| until = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Until>())); | |
| tail = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Tail>()); | |
| } | |
| ULONGLONG since = 0; | |
| if (context.Args.Contains(ArgType::Since)) | |
| { | |
| since = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Since>()); | |
| } | |
| ULONGLONG until = 0; | |
| if (context.Args.Contains(ArgType::Until)) | |
| { | |
| until = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Until>()); |
| tail = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Tail>())); | ||
| } | ||
|
|
||
| ULONGLONG since = 0; | ||
| if (context.Args.Contains(ArgType::Since)) | ||
| { | ||
| since = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Since>())); | ||
| } | ||
|
|
||
| ULONGLONG until = 0; | ||
| if (context.Args.Contains(ArgType::Until)) | ||
| { | ||
| until = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Until>())); |
There was a problem hiding this comment.
Same as --since: parsing --until via std::stoull can throw and skip the CLI's normal argument-error handling. Use the repo's integer parsing/validation helpers so bad values surface as a clear user-facing argument error.
| tail = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Tail>())); | |
| } | |
| ULONGLONG since = 0; | |
| if (context.Args.Contains(ArgType::Since)) | |
| { | |
| since = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Since>())); | |
| } | |
| ULONGLONG until = 0; | |
| if (context.Args.Contains(ArgType::Until)) | |
| { | |
| until = std::stoull(WideToMultiByte(context.Args.Get<ArgType::Until>())); | |
| tail = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Tail>()); | |
| } | |
| ULONGLONG since = 0; | |
| if (context.Args.Contains(ArgType::Since)) | |
| { | |
| since = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Since>()); | |
| } | |
| ULONGLONG until = 0; | |
| if (context.Args.Contains(ArgType::Until)) | |
| { | |
| until = validation::GetIntegerFromString<ULONGLONG>(context.Args.Get<ArgType::Until>()); |
| Argument::Create(ArgType::Tail), | ||
| Argument::Create(ArgType::Since), | ||
| Argument::Create(ArgType::Until), | ||
| Argument::Create(ArgType::Timestamps), |
There was a problem hiding this comment.
This command adds --since/--until arguments, but the new E2E suite only covers --tail, --timestamps, and --follow. Add at least one end-to-end test that exercises --since and --until filtering (or validates their error handling) to ensure these options remain functional.
|
--tail/--since/--until use raw std::stoull with no error handling. Invalid input will crash instead of giving a useful error. Use validation::GetIntegerFromString like the rest of the codebase. Also --since and --until have no test coverage. |
Summary of the Pull Request
--tail,--since,--until, and--timestampsoptions to wslc container logs.PR Checklist
Detailed Description of the Pull Request / Additional comments
Validation Steps Performed