Skip to content

Commit

Permalink
New UVSServerCommandlet for VS Unreal Engine Server Mode, and test fi…
Browse files Browse the repository at this point in the history
…lter bug fix.
  • Loading branch information
DavidARaygoza committed Dec 8, 2023
1 parent c4a9572 commit 16993d4
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 4 deletions.
114 changes: 114 additions & 0 deletions Source/VisualStudioTools/Private/VSServerCommandlet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2022 (c) Microsoft. All rights reserved.

#include "VSServerCommandlet.h"
#include "VSTestAdapterCommandlet.h"

#include "HAL/PlatformNamedPipe.h"
#include "Runtime/Core/Public/Async/TaskGraphInterfaces.h"
#include "Runtime/Core/Public/Containers/Ticker.h"
#include "Runtime/Engine/Classes/Engine/World.h"
#include "Runtime/Engine/Public/TimerManager.h"
#include "Runtime/Launch/Resources/Version.h"
#include "Runtime\CoreUObject\Public\UObject\UObjectGlobals.h"
#include <chrono>
#include <codecvt>
#include <fstream>
#include <string>
#include <thread>
#include <windows.h>

#include "VisualStudioTools.h"

static constexpr auto NamedPipeParam = TEXT("NamedPipe");
static constexpr auto KillServerParam = TEXT("KillVSServer");

UVSServerCommandlet::UVSServerCommandlet()
{
HelpDescription = TEXT("Commandlet for Unreal Engine server mode.");
HelpUsage = TEXT("<Editor-Cmd.exe> <path_to_uproject> -run=VSServer [-stdout -multiprocess -silent -unattended -AllowStdOutLogVerbosity -NoShaderCompile]");

HelpParamNames.Add(NamedPipeParam);
HelpParamDescriptions.Add(TEXT("[Required] The name of the named pipe used to communicate with Visual Studio."));

HelpParamNames.Add(KillServerParam);
HelpParamDescriptions.Add(TEXT("[Optional] Quit the server mode commandlet immediately."));
}

void UVSServerCommandlet::ExecuteSubCommandlet(FString ueServerNamedPipe)
{
char buffer[1024];
DWORD dwRead;
std::string result = "0";

// Open the named pipe.
std::wstring pipeName = L"\\\\.\\pipe\\";
pipeName.append(ueServerNamedPipe.GetCharArray().GetData());
HANDLE HPipe = CreateFile(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (HPipe != INVALID_HANDLE_VALUE)
{
ConnectNamedPipe(HPipe, NULL);
DWORD dwState;
BOOL bSuccess = GetNamedPipeHandleState(HPipe, &dwState, NULL, NULL, NULL, NULL, 0);
if (bSuccess)
{
// Read data from the named pipe.
ReadFile(HPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL);
buffer[dwRead] = '\0';
std::string strSubCommandletParams(buffer, dwRead);
FString SubCommandletParams = FString(strSubCommandletParams.c_str());

// Determine which sub-commandlet to invoke, and write back result response.
if (SubCommandletParams.Contains("VSTestAdapter"))
{
UVSTestAdapterCommandlet *Commandlet = NewObject<UVSTestAdapterCommandlet>();
try
{
int32 subCommandletResult = Commandlet->Main(SubCommandletParams);
}
catch (const std::exception &ex)
{
UE_LOG(LogVisualStudioTools, Display, TEXT("Exception invoking VSTestAdapter commandlet: %s"), UTF8_TO_TCHAR(ex.what()));
result = "0";
}
}
else if (SubCommandletParams.Contains("KillVSServer"))
{
// When KillVSServer is passed in, then kill the Unreal Editor process to end server mode.
exit(0);
}
else
{
// If cannot find which sub-commandlet to run, then return error.
result = "1";
}

WriteFile(HPipe, result.c_str(), result.size(), &dwRead, NULL);
}
}
}

int32 UVSServerCommandlet::Main(const FString &ServerParams)
{
TArray<FString> Tokens;
TArray<FString> Switches;
TMap<FString, FString> ParamVals;

ParseCommandLine(*ServerParams, Tokens, Switches, ParamVals);
if (ParamVals.Contains(NamedPipeParam))
{
FString ueServerNamedPipe = ParamVals[NamedPipeParam];

// Infinite loop that listens to requests every second.
while (true)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
ExecuteSubCommandlet(ueServerNamedPipe);
}
}
else
{
UE_LOG(LogVisualStudioTools, Display, TEXT("Missing named pipe parameter."));
}

return 1;
}
29 changes: 29 additions & 0 deletions Source/VisualStudioTools/Private/VSServerCommandlet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2022 (c) Microsoft. All rights reserved.
// Licensed under the MIT License.

#pragma once

#include "Commandlets/Commandlet.h"
#include <string>

#include <Runtime/Core/Public/Misc/AutomationTest.h>
#include <Runtime/CoreUObject/Public/UObject/ObjectMacros.h>
#include <Runtime/Engine/Classes/Commandlets/Commandlet.h>

#include "VSServerCommandlet.generated.h"

UCLASS()
class UVSServerCommandlet
: public UCommandlet
{
GENERATED_BODY()

public:
UVSServerCommandlet();

public:
virtual int32 Main(const FString& Params) override;

private:
void ExecuteSubCommandlet(FString ueServerNamedPipe);
};
14 changes: 11 additions & 3 deletions Source/VisualStudioTools/Private/VSTestAdapterCommandlet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ static int32 ListTests(const FString& TargetFile)
}

UE_LOG(LogVisualStudioTools, Display, TEXT("Found %d tests"), TestInfos.Num());

OutFile.close();

return 0;
}

Expand Down Expand Up @@ -182,7 +182,7 @@ UVSTestAdapterCommandlet::UVSTestAdapterCommandlet()
HelpParamDescriptions.Add(TEXT("[Required] The output file from running test cases that we parse to retrieve test case results."));

HelpParamNames.Add(FiltersParam);
HelpParamDescriptions.Add(TEXT("[Optional] List of test filters to enable separated by '+'. Default is 'smoke+product+perf+stress+negative'"));
HelpParamDescriptions.Add(TEXT("[Optional] List of test filters to enable separated by '+'. Default is 'application+smoke+product+perf+stress+negative'"));

HelpParamNames.Add(HelpParam);
HelpParamDescriptions.Add(TEXT("[Optional] Print this help message and quit the commandlet immediately."));
Expand Down Expand Up @@ -214,11 +214,19 @@ int32 UVSTestAdapterCommandlet::Main(const FString& Params)
}

// Default to all the test filters on except for engine tests.
uint32 filter = EAutomationTestFlags::ProductFilter | EAutomationTestFlags::SmokeFilter |
uint32 filter = EAutomationTestFlags::ProductFilter | EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::SmokeFilter |
EAutomationTestFlags::PerfFilter | EAutomationTestFlags::StressFilter | EAutomationTestFlags::NegativeFilter;
if (ParamVals.Contains(FiltersParam))
{
FString filters = ParamVals[FiltersParam];
if (filters.Contains("application"))
{
filter |= EAutomationTestFlags::ApplicationContextMask;
}
else
{
filter &= ~EAutomationTestFlags::ApplicationContextMask;
}
if (filters.Contains("smoke"))
{
filter |= EAutomationTestFlags::SmokeFilter;
Expand Down
2 changes: 1 addition & 1 deletion VisualStudioTools.uplugin
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "2.3",
"VersionName": "2.4",
"FriendlyName": "Visual Studio Integration Tools",
"Description": "Enables integration with Visual Studio IDE.",
"Category": "Programming",
Expand Down

0 comments on commit 16993d4

Please sign in to comment.