32fbd4cbb6
This commit is a preparation for upcoming changes to KeyChordSerialization for #7539 and #10203. In order to support variadic macros, /Zc:preprocessor was enabled, which required changing unrelated parts of the project. ## PR Checklist * [x] I work here * [x] Tests added/passed ## Validation Steps Performed * Project still compiles ✔️
2372 lines
99 KiB
C++
2372 lines
99 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "pch.h"
|
|
#include "../Remoting/Monarch.h"
|
|
#include "../Remoting/CommandlineArgs.h"
|
|
#include "../Remoting/FindTargetWindowArgs.h"
|
|
#include "../Remoting/ProposeCommandlineResult.h"
|
|
#include "../inc/WindowingBehavior.h"
|
|
|
|
using namespace Microsoft::Console;
|
|
using namespace WEX::Logging;
|
|
using namespace WEX::TestExecution;
|
|
using namespace WEX::Common;
|
|
|
|
using namespace winrt;
|
|
using namespace winrt::Microsoft::Terminal;
|
|
|
|
namespace RemotingUnitTests
|
|
{
|
|
struct MockDesktopManager : implements<MockDesktopManager, IVirtualDesktopManager>
|
|
{
|
|
IFACEMETHOD(GetWindowDesktopId)
|
|
(HWND /*topLevelWindow*/, GUID* /*desktopId*/)
|
|
{
|
|
VERIFY_IS_TRUE(false, L"We shouldn't need GetWindowDesktopId in the tests.");
|
|
return E_FAIL;
|
|
}
|
|
IFACEMETHOD(MoveWindowToDesktop)
|
|
(HWND /*topLevelWindow*/, REFGUID /*desktopId*/)
|
|
{
|
|
VERIFY_IS_TRUE(false, L"We shouldn't need GetWindowDesktopId in the tests.");
|
|
return E_FAIL;
|
|
}
|
|
IFACEMETHOD(IsWindowOnCurrentVirtualDesktop)
|
|
(HWND topLevelWindow, BOOL* onCurrentDesktop)
|
|
{
|
|
if (pfnIsWindowOnCurrentVirtualDesktop)
|
|
{
|
|
return pfnIsWindowOnCurrentVirtualDesktop(topLevelWindow, onCurrentDesktop);
|
|
}
|
|
VERIFY_IS_TRUE(false, L"You didn't set up the pfnIsWindowOnCurrentVirtualDesktop for this test!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
std::function<HRESULT(HWND, BOOL*)> pfnIsWindowOnCurrentVirtualDesktop;
|
|
};
|
|
|
|
// This is a silly helper struct.
|
|
// It will always throw an hresult_error on any of its methods.
|
|
//
|
|
// In the tests, it's hard to emulate a peasant process being totally dead
|
|
// once the Monarch has captured a reference to it. Since everything's
|
|
// in-proc in the tests, we can't decrement the refcount in such a way that
|
|
// the monarch's reference will throw a catchable exception. Instead, this
|
|
// class can be used to replace a peasant inside a Monarch, to emulate that
|
|
// peasant process dying. Any time the monarch tries to do something to this
|
|
// peasant, it'll throw an exception.
|
|
struct DeadPeasant : implements<DeadPeasant, winrt::Microsoft::Terminal::Remoting::IPeasant>
|
|
{
|
|
DeadPeasant() = default;
|
|
void AssignID(uint64_t /*id*/) { throw winrt::hresult_error{}; };
|
|
uint64_t GetID() { throw winrt::hresult_error{}; };
|
|
winrt::hstring WindowName() { throw winrt::hresult_error{}; };
|
|
uint64_t GetPID() { throw winrt::hresult_error{}; };
|
|
bool ExecuteCommandline(const Remoting::CommandlineArgs& /*args*/) { throw winrt::hresult_error{}; }
|
|
void ActivateWindow(const Remoting::WindowActivatedArgs& /*args*/) { throw winrt::hresult_error{}; }
|
|
void RequestIdentifyWindows() { throw winrt::hresult_error{}; };
|
|
void DisplayWindowId() { throw winrt::hresult_error{}; };
|
|
Remoting::CommandlineArgs InitialArgs() { throw winrt::hresult_error{}; }
|
|
Remoting::WindowActivatedArgs GetLastActivatedArgs() { throw winrt::hresult_error{}; }
|
|
void RequestRename(const Remoting::RenameRequestArgs& /*args*/) { throw winrt::hresult_error{}; }
|
|
void Summon(const Remoting::SummonWindowBehavior& /*args*/) { throw winrt::hresult_error{}; };
|
|
TYPED_EVENT(WindowActivated, winrt::Windows::Foundation::IInspectable, Remoting::WindowActivatedArgs);
|
|
TYPED_EVENT(ExecuteCommandlineRequested, winrt::Windows::Foundation::IInspectable, Remoting::CommandlineArgs);
|
|
TYPED_EVENT(IdentifyWindowsRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
|
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
|
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, Remoting::RenameRequestArgs);
|
|
TYPED_EVENT(SummonRequested, winrt::Windows::Foundation::IInspectable, Remoting::SummonWindowBehavior);
|
|
};
|
|
|
|
class RemotingTests
|
|
{
|
|
BEGIN_TEST_CLASS(RemotingTests)
|
|
END_TEST_CLASS()
|
|
|
|
TEST_METHOD(CreateMonarch);
|
|
TEST_METHOD(CreatePeasant);
|
|
TEST_METHOD(CreatePeasantWithNew);
|
|
TEST_METHOD(AddPeasants);
|
|
TEST_METHOD(GetPeasantsByID);
|
|
TEST_METHOD(AddPeasantsToNewMonarch);
|
|
TEST_METHOD(RemovePeasantFromMonarchWhenFreed);
|
|
|
|
TEST_METHOD(ProposeCommandlineNoWindow);
|
|
TEST_METHOD(ProposeCommandlineGivenWindow);
|
|
TEST_METHOD(ProposeCommandlineNegativeWindow);
|
|
TEST_METHOD(ProposeCommandlineCurrentWindow);
|
|
TEST_METHOD(ProposeCommandlineNonExistentWindow);
|
|
TEST_METHOD(ProposeCommandlineDeadWindow);
|
|
|
|
TEST_METHOD(MostRecentWindowSameDesktops);
|
|
TEST_METHOD(MostRecentWindowDifferentDesktops);
|
|
TEST_METHOD(MostRecentWindowMoveDesktops);
|
|
TEST_METHOD(GetMostRecentAnyDesktop);
|
|
TEST_METHOD(MostRecentIsDead);
|
|
|
|
TEST_METHOD(MostRecentIsQuake);
|
|
|
|
TEST_METHOD(GetPeasantsByName);
|
|
TEST_METHOD(AddNamedPeasantsToNewMonarch);
|
|
TEST_METHOD(LookupNamedPeasantWhenOthersDied);
|
|
TEST_METHOD(LookupNamedPeasantWhenItDied);
|
|
TEST_METHOD(GetMruPeasantAfterNameLookupForDeadPeasant);
|
|
|
|
TEST_METHOD(ProposeCommandlineForNamedDeadWindow);
|
|
|
|
TEST_METHOD(TestRenameWindowSuccessfully);
|
|
TEST_METHOD(TestRenameSameNameAsAnother);
|
|
TEST_METHOD(TestRenameSameNameAsADeadPeasant);
|
|
|
|
TEST_METHOD(TestSummonMostRecentWindow);
|
|
TEST_METHOD(TestSummonNamedWindow);
|
|
TEST_METHOD(TestSummonNamedDeadWindow);
|
|
TEST_METHOD(TestSummonMostRecentDeadWindow);
|
|
|
|
TEST_METHOD(TestSummonOnCurrent);
|
|
TEST_METHOD(TestSummonOnCurrentWithName);
|
|
TEST_METHOD(TestSummonOnCurrentDeadWindow);
|
|
|
|
TEST_METHOD(TestSummonMostRecentIsQuake);
|
|
|
|
TEST_CLASS_SETUP(ClassSetup)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static void _killPeasant(const com_ptr<Remoting::implementation::Monarch>& m,
|
|
const uint64_t peasantID);
|
|
|
|
static void _findTargetWindowHelper(const winrt::Windows::Foundation::IInspectable& sender,
|
|
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args);
|
|
|
|
static void _findTargetWindowByNameHelper(const winrt::Windows::Foundation::IInspectable& sender,
|
|
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args);
|
|
|
|
// This template that lets us call a private ctor for Monarch/Peasant, unlike make_self.
|
|
// Currently I use a private implementation detail of winrt::make_self,
|
|
// which is bad, but I didn't want to deal with the alternatives.
|
|
template<typename T, typename... Args>
|
|
static winrt::com_ptr<T> make_private(Args&&... args)
|
|
{
|
|
return { new winrt::impl::heap_implements<T>(std::forward<Args>(args)...), winrt::take_ownership_from_abi };
|
|
}
|
|
};
|
|
|
|
// Helper to replace the specified peasant in a monarch with a
|
|
// "DeadPeasant", which will emulate what happens when the peasant process
|
|
// dies.
|
|
void RemotingTests::_killPeasant(const com_ptr<Remoting::implementation::Monarch>& m,
|
|
const uint64_t peasantID)
|
|
{
|
|
if (peasantID <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m->_peasants[peasantID] = winrt::make<DeadPeasant>();
|
|
}
|
|
|
|
// Helper to get the first argument out of the commandline, and try to
|
|
// convert it to an int.
|
|
void RemotingTests::_findTargetWindowHelper(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args)
|
|
{
|
|
const auto arguments = args.Args().Commandline();
|
|
if (arguments.size() > 0)
|
|
{
|
|
const auto index = std::stoi(arguments.at(0).c_str());
|
|
args.ResultTargetWindow(index >= 0 ? index : -1);
|
|
}
|
|
}
|
|
|
|
// Helper to get the first argument out of the commandline, and return it as
|
|
// a name to use.
|
|
void RemotingTests::_findTargetWindowByNameHelper(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
|
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args)
|
|
{
|
|
const auto arguments = args.Args().Commandline();
|
|
if (arguments.size() > 0)
|
|
{
|
|
args.ResultTargetWindow(WindowingBehaviorUseName);
|
|
args.ResultTargetWindowName(arguments.at(0));
|
|
}
|
|
}
|
|
|
|
void RemotingTests::CreateMonarch()
|
|
{
|
|
auto m1 = make_private<Remoting::implementation::Monarch>();
|
|
VERIFY_ARE_EQUAL(GetCurrentProcessId(),
|
|
m1->GetPID(),
|
|
L"A Monarch without an explicit PID should use the current PID");
|
|
|
|
Log::Comment(L"That's what we need for window process management, but for tests, it'll be more useful to fake the PIDs.");
|
|
|
|
auto expectedFakePID = 1234u;
|
|
auto m2 = make_private<Remoting::implementation::Monarch>(expectedFakePID);
|
|
VERIFY_ARE_EQUAL(expectedFakePID,
|
|
m2->GetPID(),
|
|
L"A Monarch with an explicit PID should use the one we provided");
|
|
}
|
|
|
|
void RemotingTests::CreatePeasant()
|
|
{
|
|
auto p1 = make_private<Remoting::implementation::Peasant>();
|
|
VERIFY_ARE_EQUAL(GetCurrentProcessId(),
|
|
p1->GetPID(),
|
|
L"A Peasant without an explicit PID should use the current PID");
|
|
|
|
Log::Comment(L"That's what we need for window process management, but for tests, it'll be more useful to fake the PIDs.");
|
|
|
|
auto expectedFakePID = 2345u;
|
|
auto p2 = make_private<Remoting::implementation::Monarch>(expectedFakePID);
|
|
VERIFY_ARE_EQUAL(expectedFakePID,
|
|
p2->GetPID(),
|
|
L"A Peasant with an explicit PID should use the one we provided");
|
|
}
|
|
|
|
void RemotingTests::CreatePeasantWithNew()
|
|
{
|
|
Log::Comment(L"The same thing as the above test, but with `new` instead of insanity on the stack");
|
|
|
|
auto p1 = make_private<Remoting::implementation::Peasant>();
|
|
VERIFY_ARE_EQUAL(GetCurrentProcessId(),
|
|
p1->GetPID(),
|
|
L"A Peasant without an explicit PID should use the current PID");
|
|
|
|
auto expectedFakePID = 2345u;
|
|
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(expectedFakePID);
|
|
VERIFY_ARE_EQUAL(expectedFakePID,
|
|
p2->GetPID(),
|
|
L"A Peasant with an explicit PID should use the one we provided");
|
|
}
|
|
|
|
void RemotingTests::AddPeasants()
|
|
{
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
}
|
|
|
|
void RemotingTests::GetPeasantsByID()
|
|
{
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
auto maybeP1 = m0->_getPeasant(1);
|
|
VERIFY_ARE_EQUAL(peasant1PID, maybeP1.GetPID());
|
|
|
|
auto maybeP2 = m0->_getPeasant(2);
|
|
VERIFY_ARE_EQUAL(peasant2PID, maybeP2.GetPID());
|
|
}
|
|
|
|
void RemotingTests::AddPeasantsToNewMonarch()
|
|
{
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
const auto monarch3PID = 45678u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
auto m3 = make_private<Remoting::implementation::Monarch>(monarch3PID);
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
m3->AddPeasant(*p1);
|
|
m3->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
}
|
|
|
|
void RemotingTests::RemovePeasantFromMonarchWhenFreed()
|
|
{
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
Log::Comment(L"Kill peasant 1. Make sure that it gets removed from the monarch.");
|
|
RemotingTests::_killPeasant(m0, p1->GetID());
|
|
|
|
auto maybeP2 = m0->_getPeasant(2);
|
|
VERIFY_ARE_EQUAL(peasant2PID, maybeP2.GetPID());
|
|
|
|
auto maybeP1 = m0->_getPeasant(1);
|
|
VERIFY_IS_NULL(maybeP1);
|
|
|
|
VERIFY_ARE_EQUAL(1u, m0->_peasants.size());
|
|
}
|
|
|
|
void RemotingTests::ProposeCommandlineNoWindow()
|
|
{
|
|
Log::Comment(L"Test proposing a commandline that doesn't have a window specified in it");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
std::vector<winrt::hstring> args{};
|
|
Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Propose the same args again after adding a peasant - we should still return {create new window, no ID}");
|
|
result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
|
|
void RemotingTests::ProposeCommandlineGivenWindow()
|
|
{
|
|
Log::Comment(L"Test proposing a commandline for a window that currently exists");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
p1->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& cmdlineArgs) {
|
|
Log::Comment(L"Commandline dispatched to p1");
|
|
VERIFY_IS_GREATER_THAN(cmdlineArgs.Commandline().size(), 1u);
|
|
VERIFY_ARE_EQUAL(L"arg[1]", cmdlineArgs.Commandline().at(1));
|
|
});
|
|
|
|
std::vector<winrt::hstring> args{ L"1", L"arg[1]" };
|
|
Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
void RemotingTests::ProposeCommandlineNegativeWindow()
|
|
{
|
|
Log::Comment(L"Test proposing a commandline for an invalid window ID, like -1");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
{
|
|
std::vector<winrt::hstring> args{ L"-1" };
|
|
Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
{
|
|
std::vector<winrt::hstring> args{ L"-2" };
|
|
Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
}
|
|
void RemotingTests::ProposeCommandlineCurrentWindow()
|
|
{
|
|
Log::Comment(L"Test proposing a commandline for the current window (ID=0)");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
p1->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& cmdlineArgs) {
|
|
Log::Comment(L"Commandline dispatched to p1");
|
|
VERIFY_IS_GREATER_THAN(cmdlineArgs.Commandline().size(), 1u);
|
|
VERIFY_ARE_EQUAL(L"arg[1]", cmdlineArgs.Commandline().at(1));
|
|
});
|
|
|
|
std::vector<winrt::hstring> p1Args{ L"0", L"arg[1]" };
|
|
std::vector<winrt::hstring> p2Args{ L"0", L"this is for p2" };
|
|
|
|
{
|
|
Log::Comment(L"Manually activate the first peasant");
|
|
// This would usually happen immediately when the window is created, but
|
|
// there's no actual window in these tests.
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
winrt::guid{},
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
|
|
Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
m0->AddPeasant(*p2);
|
|
p2->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& cmdlineArgs) {
|
|
Log::Comment(L"Commandline dispatched to p2");
|
|
VERIFY_IS_GREATER_THAN(cmdlineArgs.Commandline().size(), 1u);
|
|
VERIFY_ARE_EQUAL(L"this is for p2", cmdlineArgs.Commandline().at(1));
|
|
});
|
|
|
|
{
|
|
Log::Comment(L"Activate the second peasant");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
winrt::guid{},
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
|
|
Log::Comment(L"Send a commandline to the current window, which should be p2");
|
|
Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
{
|
|
Log::Comment(L"Reactivate the first peasant");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
winrt::guid{},
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
|
|
Log::Comment(L"Send a commandline to the current window, which should be p1 again");
|
|
Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
}
|
|
void RemotingTests::ProposeCommandlineNonExistentWindow()
|
|
{
|
|
Log::Comment(L"Test proposing a commandline for an ID that doesn't have a current peasant");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
{
|
|
std::vector<winrt::hstring> args{ L"2" };
|
|
Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(true, (bool)result.Id());
|
|
VERIFY_ARE_EQUAL(2u, result.Id().Value());
|
|
}
|
|
{
|
|
std::vector<winrt::hstring> args{ L"10" };
|
|
Remoting::CommandlineArgs eventArgs{ { args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(true, (bool)result.Id());
|
|
VERIFY_ARE_EQUAL(10u, result.Id().Value());
|
|
}
|
|
}
|
|
|
|
void RemotingTests::ProposeCommandlineDeadWindow()
|
|
{
|
|
Log::Comment(L"Test proposing a commandline for a peasant that previously died");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
p1->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& /*cmdlineArgs*/) {
|
|
Log::Comment(L"Commandline dispatched to p1");
|
|
VERIFY_IS_TRUE(false, L"This should not happen, this peasant should be dead.");
|
|
});
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
m0->AddPeasant(*p2);
|
|
p2->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& cmdlineArgs) {
|
|
Log::Comment(L"Commandline dispatched to p2");
|
|
VERIFY_IS_GREATER_THAN(cmdlineArgs.Commandline().size(), 1u);
|
|
VERIFY_ARE_EQUAL(L"this is for p2", cmdlineArgs.Commandline().at(1));
|
|
});
|
|
|
|
std::vector<winrt::hstring> p1Args{ L"1", L"arg[1]" };
|
|
std::vector<winrt::hstring> p2Args{ L"2", L"this is for p2" };
|
|
|
|
Log::Comment(L"Kill peasant 1");
|
|
|
|
_killPeasant(m0, 1);
|
|
|
|
{
|
|
Log::Comment(L"Send a commandline to p2, who is still alive. We won't create a new window.");
|
|
|
|
Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
}
|
|
{
|
|
Log::Comment(L"Send a commandline to p1, who is dead. We will create a new window.");
|
|
Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
|
|
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(true, (bool)result.Id());
|
|
VERIFY_ARE_EQUAL(1u, result.Id().Value());
|
|
}
|
|
}
|
|
|
|
// TODO:projects/5
|
|
//
|
|
// In order to test WindowingBehaviorUseExisting, we'll have to
|
|
// create our own IVirtualDesktopManager implementation that can be subbed
|
|
// in for testing. We can't _actually_ create HWNDs as a part of the test
|
|
// and move them to different desktops. Instead, we'll have to create a stub
|
|
// impl that can fake a result for IsWindowOnCurrentVirtualDesktop.
|
|
|
|
void RemotingTests::MostRecentWindowSameDesktops()
|
|
{
|
|
Log::Comment(L"Make windows on the same desktop. Validate the contents of _mruPeasants are as expected.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
m0->AddPeasant(*p2);
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(2u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(2u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
}
|
|
|
|
void RemotingTests::MostRecentWindowDifferentDesktops()
|
|
{
|
|
Log::Comment(L"Make windows on different desktops. Validate the contents of _mruPeasants are as expected.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
m0->AddPeasant(*p2);
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(2u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
|
|
Log::Comment(L"Add a third peasant");
|
|
const auto peasant3PID = 45678u;
|
|
auto p3 = make_private<Remoting::implementation::Peasant>(peasant3PID);
|
|
m0->AddPeasant(*p3);
|
|
{
|
|
Log::Comment(L"Activate the third peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(3u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p3->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[2].PeasantID());
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(3u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p3->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[2].PeasantID());
|
|
}
|
|
|
|
void RemotingTests::MostRecentWindowMoveDesktops()
|
|
{
|
|
Log::Comment(L"Make windows on different desktops. Move one to another "
|
|
L"desktop. Validate the contents of _mruPeasants are as expected.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
m0->AddPeasant(*p2);
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(2u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
|
|
Log::Comment(L"Add a third peasant");
|
|
const auto peasant3PID = 45678u;
|
|
auto p3 = make_private<Remoting::implementation::Peasant>(peasant3PID);
|
|
m0->AddPeasant(*p3);
|
|
{
|
|
Log::Comment(L"Activate the third peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(3u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p3->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[2].PeasantID());
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(3u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p3->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[2].PeasantID());
|
|
|
|
{
|
|
Log::Comment(L"Activate the third peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(3u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p3->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[2].PeasantID());
|
|
|
|
{
|
|
Log::Comment(L"Activate the second peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(3u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p3->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[2].PeasantID());
|
|
}
|
|
|
|
void RemotingTests::GetMostRecentAnyDesktop()
|
|
{
|
|
Log::Comment(L"Make windows on different desktops. Confirm that "
|
|
L"getting the most recent of all windows works as expected.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
m0->AddPeasant(*p2);
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
|
|
Log::Comment(L"Add a third peasant");
|
|
const auto peasant3PID = 45678u;
|
|
auto p3 = make_private<Remoting::implementation::Peasant>(peasant3PID);
|
|
m0->AddPeasant(*p3);
|
|
{
|
|
Log::Comment(L"Activate the third peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(p3->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
}
|
|
|
|
void RemotingTests::MostRecentIsDead()
|
|
{
|
|
Log::Comment(L"Make two windows. Activate the first, then the second. "
|
|
L"Kill the second. The most recent should be the _first_ window.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
m0->AddPeasant(*p2);
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
VERIFY_ARE_EQUAL(2u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
|
|
Log::Comment(L"Kill peasant 2");
|
|
RemotingTests::_killPeasant(m0, p2->GetID());
|
|
Log::Comment(L"Peasant 1 should be the new MRU peasant");
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
|
|
Log::Comment(L"Peasant 2 should not be in the monarch at all anymore");
|
|
VERIFY_ARE_EQUAL(1u, m0->_peasants.size());
|
|
VERIFY_ARE_EQUAL(1u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(1u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
}
|
|
|
|
void RemotingTests::MostRecentIsQuake()
|
|
{
|
|
Log::Comment(L"When a window is named _quake, it shouldn't participate "
|
|
L"in window glomming via the MRU window.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"_quake");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the _quake peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
|
|
Log::Comment(L"When we look up the MRU window, we find peasant 1 (who's name is \"one\"), not 2 (who's name is \"_quake\")");
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"_quake"));
|
|
|
|
{
|
|
Log::Comment(L"rename p2 to \"two\"");
|
|
Remoting::RenameRequestArgs eventArgs{ L"two" };
|
|
p2->RequestRename(eventArgs);
|
|
VERIFY_IS_TRUE(eventArgs.Succeeded());
|
|
}
|
|
VERIFY_ARE_EQUAL(L"two", p2->WindowName());
|
|
|
|
Log::Comment(L"Now, the MRU window will correctly be p2");
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
{
|
|
Log::Comment(L"rename p1 to \"_quake\"");
|
|
Remoting::RenameRequestArgs eventArgs{ L"_quake" };
|
|
p1->RequestRename(eventArgs);
|
|
VERIFY_IS_TRUE(eventArgs.Succeeded());
|
|
}
|
|
VERIFY_ARE_EQUAL(L"_quake", p1->WindowName());
|
|
|
|
Log::Comment(L"Now, the MRU window will still be p2");
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"_quake"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
Log::Comment(L"Now, the MRU window will still be p2, because p1 is still named \"_quake\"");
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"_quake"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
}
|
|
|
|
void RemotingTests::GetPeasantsByName()
|
|
{
|
|
Log::Comment(L"Test that looking up a peasant by name finds the window we expect");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
VERIFY_ARE_EQUAL(L"one", p1->WindowName());
|
|
VERIFY_ARE_EQUAL(L"two", p2->WindowName());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
VERIFY_ARE_EQUAL(L"one", p1->WindowName());
|
|
VERIFY_ARE_EQUAL(L"two", p2->WindowName());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
Log::Comment(L"Rename p2");
|
|
|
|
p2->WindowName(L"foo");
|
|
|
|
VERIFY_ARE_EQUAL(0, m0->_lookupPeasantIdForName(L"two"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"foo"));
|
|
}
|
|
|
|
void RemotingTests::AddNamedPeasantsToNewMonarch()
|
|
{
|
|
Log::Comment(L"Test that moving peasants to a new monarch persists their original names");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
const auto monarch3PID = 45678u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
auto m3 = make_private<Remoting::implementation::Monarch>(monarch3PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
VERIFY_ARE_EQUAL(L"one", p1->WindowName());
|
|
VERIFY_ARE_EQUAL(L"two", p2->WindowName());
|
|
|
|
Log::Comment(L"When the peasants go to a new monarch, make sure they have the same name");
|
|
m3->AddPeasant(*p1);
|
|
m3->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
VERIFY_ARE_EQUAL(L"one", p1->WindowName());
|
|
VERIFY_ARE_EQUAL(L"two", p2->WindowName());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m3->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m3->_lookupPeasantIdForName(L"two"));
|
|
}
|
|
|
|
void RemotingTests::LookupNamedPeasantWhenOthersDied()
|
|
{
|
|
Log::Comment(L"Test that looking for a peasant by name when a different"
|
|
L" peasant has died cleans up the corpses of any peasants "
|
|
L"we may have tripped over.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
Log::Comment(L"Kill peasant 1. Make sure that it gets removed from the monarch.");
|
|
RemotingTests::_killPeasant(m0, p1->GetID());
|
|
|
|
// By killing 1, then looking for "two", we happen to iterate over the
|
|
// corpse of 1 when looking for the peasant named "two". This causes us
|
|
// to remove 1 while looking for "two". Technically, we shouldn't be
|
|
// relying on any sort of ordering for an unordered_map iterator, but
|
|
// this one just so happens to work.
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
Log::Comment(L"Peasant 1 should have been pruned");
|
|
VERIFY_ARE_EQUAL(1u, m0->_peasants.size());
|
|
}
|
|
|
|
void RemotingTests::LookupNamedPeasantWhenItDied()
|
|
{
|
|
Log::Comment(L"Test that looking up a dead peasant by name returns 0, "
|
|
L"indicating there's no peasant with that name.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
Log::Comment(L"Kill peasant 1. Make sure that it gets removed from the monarch.");
|
|
RemotingTests::_killPeasant(m0, p1->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(0, m0->_lookupPeasantIdForName(L"one"));
|
|
|
|
Log::Comment(L"Peasant 1 should have been pruned");
|
|
VERIFY_ARE_EQUAL(1u, m0->_peasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
}
|
|
|
|
void RemotingTests::GetMruPeasantAfterNameLookupForDeadPeasant()
|
|
{
|
|
// This test is trying to hit the catch in Monarch::_lookupPeasantIdForName.
|
|
//
|
|
// We need to:
|
|
// * add some peasants,
|
|
// * make one the mru, then make a named two the mru
|
|
// * then kill two
|
|
// * then try to get the mru peasant -> it should be one
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
Log::Comment(L"Kill peasant 2.");
|
|
RemotingTests::_killPeasant(m0, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_getMostRecentPeasantID(false, true));
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_getMostRecentPeasantID(true, true));
|
|
}
|
|
|
|
void RemotingTests::ProposeCommandlineForNamedDeadWindow()
|
|
{
|
|
Log::Comment(L"Test proposing a commandline for a named window that's "
|
|
L"currently dead. This should result in a new window with "
|
|
L"the given name.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowByNameHelper);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
p1->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& cmdlineArgs) {
|
|
Log::Comment(L"Commandline dispatched to p1");
|
|
VERIFY_IS_GREATER_THAN(cmdlineArgs.Commandline().size(), 1u);
|
|
VERIFY_ARE_EQUAL(L"arg[1]", cmdlineArgs.Commandline().at(1));
|
|
});
|
|
p2->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& cmdlineArgs) {
|
|
Log::Comment(L"Commandline dispatched to p2");
|
|
VERIFY_IS_GREATER_THAN(cmdlineArgs.Commandline().size(), 1u);
|
|
VERIFY_ARE_EQUAL(L"this is for p2", cmdlineArgs.Commandline().at(1));
|
|
});
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
std::vector<winrt::hstring> p1Args{ L"one", L"arg[1]" };
|
|
std::vector<winrt::hstring> p2Args{ L"two", L"this is for p2" };
|
|
|
|
{
|
|
Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" } };
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value
|
|
VERIFY_ARE_EQUAL(L"", result.WindowName());
|
|
}
|
|
|
|
{
|
|
Log::Comment(L"Send a commandline to \"two\", which should be p2");
|
|
Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value
|
|
VERIFY_ARE_EQUAL(L"", result.WindowName());
|
|
}
|
|
|
|
Log::Comment(L"Kill peasant 2.");
|
|
RemotingTests::_killPeasant(m0, p2->GetID());
|
|
|
|
{
|
|
Log::Comment(L"Send a commandline to \"two\", who is now dead.");
|
|
Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" } };
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value
|
|
VERIFY_ARE_EQUAL(L"two", result.WindowName());
|
|
}
|
|
}
|
|
|
|
void RemotingTests::TestRenameWindowSuccessfully()
|
|
{
|
|
Log::Comment(L"Attempt to rename a window. This should succeed.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
Remoting::RenameRequestArgs eventArgs{ L"foo" };
|
|
p1->RequestRename(eventArgs);
|
|
|
|
VERIFY_IS_TRUE(eventArgs.Succeeded());
|
|
VERIFY_ARE_EQUAL(L"foo", p1->WindowName());
|
|
|
|
VERIFY_ARE_EQUAL(0, m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"foo"));
|
|
}
|
|
|
|
void RemotingTests::TestRenameSameNameAsAnother()
|
|
{
|
|
Log::Comment(L"Try renaming a window to a name used by another peasant."
|
|
L" This should fail.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
Remoting::RenameRequestArgs eventArgs{ L"two" };
|
|
p1->RequestRename(eventArgs);
|
|
|
|
VERIFY_IS_FALSE(eventArgs.Succeeded());
|
|
VERIFY_ARE_EQUAL(L"one", p1->WindowName());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
}
|
|
void RemotingTests::TestRenameSameNameAsADeadPeasant()
|
|
{
|
|
Log::Comment(L"We'll try renaming a window to the name of a window that"
|
|
L" has died. This should succeed, without crashing.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
Remoting::RenameRequestArgs eventArgs{ L"two" };
|
|
p1->RequestRename(eventArgs);
|
|
|
|
VERIFY_IS_FALSE(eventArgs.Succeeded());
|
|
VERIFY_ARE_EQUAL(L"one", p1->WindowName());
|
|
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"one"));
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
|
|
RemotingTests::_killPeasant(m0, p2->GetID());
|
|
|
|
p1->RequestRename(eventArgs);
|
|
|
|
VERIFY_IS_TRUE(eventArgs.Succeeded());
|
|
VERIFY_ARE_EQUAL(L"two", p1->WindowName());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_lookupPeasantIdForName(L"two"));
|
|
}
|
|
|
|
void RemotingTests::TestSummonMostRecentWindow()
|
|
{
|
|
Log::Comment(L"Attempt to summon the most recent window");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
p2ExpectedToBeSummoned = true;
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
// Without setting the WindowName, SummonWindowSelectionArgs defaults to
|
|
// the MRU window
|
|
Log::Comment(L"Summon the MRU window, which is window two");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
Log::Comment(L"Now that one is the MRU, summon it");
|
|
p2ExpectedToBeSummoned = false;
|
|
p1ExpectedToBeSummoned = true;
|
|
args.FoundMatch(false);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
}
|
|
|
|
void RemotingTests::TestSummonNamedWindow()
|
|
{
|
|
Log::Comment(L"Attempt to summon a window by name. When there isn't a "
|
|
L"window with that name, set FoundMatch to false, so the "
|
|
L"caller can handle that case.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
|
|
Log::Comment(L"Summon window two by name");
|
|
p2ExpectedToBeSummoned = true;
|
|
args.WindowName(L"two");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Summon window one by name");
|
|
p2ExpectedToBeSummoned = false;
|
|
p1ExpectedToBeSummoned = true;
|
|
args.FoundMatch(false);
|
|
args.WindowName(L"one");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Fail to summon window three by name");
|
|
p1ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.WindowName(L"three");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_FALSE(args.FoundMatch());
|
|
}
|
|
|
|
void RemotingTests::TestSummonNamedDeadWindow()
|
|
{
|
|
Log::Comment(L"Attempt to summon a dead window by name. This will fail, but not crash.");
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
|
|
Log::Comment(L"Summon window two by name");
|
|
p2ExpectedToBeSummoned = true;
|
|
args.WindowName(L"two");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Summon window one by name");
|
|
p2ExpectedToBeSummoned = false;
|
|
p1ExpectedToBeSummoned = true;
|
|
args.FoundMatch(false);
|
|
args.WindowName(L"one");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Kill peasant one.");
|
|
RemotingTests::_killPeasant(m0, p1->GetID());
|
|
|
|
Log::Comment(L"Fail to summon window one by name");
|
|
p1ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.WindowName(L"one");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_FALSE(args.FoundMatch());
|
|
}
|
|
|
|
void RemotingTests::TestSummonMostRecentDeadWindow()
|
|
{
|
|
Log::Comment(L"Attempt to summon the MRU window, when the MRU window "
|
|
L"has died. This will fall back to the next MRU window.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
p2ExpectedToBeSummoned = true;
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
// Without setting the WindowName, SummonWindowSelectionArgs defaults to
|
|
// the MRU window
|
|
Log::Comment(L"Summon the MRU window, which is window two");
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
Log::Comment(L"Now that one is the MRU, summon it");
|
|
p2ExpectedToBeSummoned = false;
|
|
p1ExpectedToBeSummoned = true;
|
|
args.FoundMatch(false);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Kill peasant one.");
|
|
RemotingTests::_killPeasant(m0, p1->GetID());
|
|
|
|
Log::Comment(L"We now expect to summon two, since the MRU peasant (one) is actually dead.");
|
|
p2ExpectedToBeSummoned = true;
|
|
p1ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
}
|
|
|
|
void RemotingTests::TestSummonOnCurrent()
|
|
{
|
|
Log::Comment(L"Tests summoning a window, using OnCurrentDesktop to only"
|
|
L"select windows on the current desktop.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
constexpr auto monarch0PID = 12345u;
|
|
constexpr auto peasant1PID = 23456u;
|
|
constexpr auto peasant2PID = 34567u;
|
|
constexpr auto peasant3PID = 45678u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
auto p3 = make_private<Remoting::implementation::Peasant>(peasant3PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
p3->WindowName(L"three");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
VERIFY_ARE_EQUAL(0, p3->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
m0->AddPeasant(*p3);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
VERIFY_ARE_EQUAL(3, p3->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(3u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
bool p3ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
p3->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p3 summoned");
|
|
VERIFY_IS_TRUE(p3ExpectedToBeSummoned);
|
|
});
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
p1->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
p2->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the third peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
p3->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
Log::Comment(L"Create a mock IVirtualDesktopManager to handle checking if a window is on a given desktop");
|
|
auto manager = winrt::make_self<MockDesktopManager>();
|
|
m0->_desktopManager = manager.try_as<IVirtualDesktopManager>();
|
|
|
|
auto firstCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
|
Log::Comment(L"firstCallback: Checking if window is on desktop 1");
|
|
|
|
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
|
if (hwnd == peasant1PID || hwnd == peasant3PID)
|
|
{
|
|
*result = true;
|
|
}
|
|
else if (hwnd == peasant2PID)
|
|
{
|
|
*result = false;
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
|
}
|
|
return S_OK;
|
|
};
|
|
manager->pfnIsWindowOnCurrentVirtualDesktop = firstCallback;
|
|
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
|
|
Log::Comment(L"Summon window three - it is the MRU on desktop 1");
|
|
p3ExpectedToBeSummoned = true;
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
p1->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
Log::Comment(L"Summon window one - it is the MRU on desktop 1");
|
|
p1ExpectedToBeSummoned = true;
|
|
p2ExpectedToBeSummoned = false;
|
|
p3ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Now we'll pretend we switched to desktop 2");
|
|
|
|
auto secondCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
|
Log::Comment(L"secondCallback: Checking if window is on desktop 2");
|
|
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
|
if (hwnd == peasant1PID || hwnd == peasant3PID)
|
|
{
|
|
*result = false;
|
|
}
|
|
else if (hwnd == peasant2PID)
|
|
{
|
|
*result = true;
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
|
}
|
|
return S_OK;
|
|
};
|
|
manager->pfnIsWindowOnCurrentVirtualDesktop = secondCallback;
|
|
|
|
Log::Comment(L"Summon window one - it is the MRU on desktop 2");
|
|
p1ExpectedToBeSummoned = false;
|
|
p2ExpectedToBeSummoned = true;
|
|
p3ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
{
|
|
Log::Comment(L"Activate the third peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
p3->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
auto thirdCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
|
Log::Comment(L"thirdCallback: Checking if window is on desktop 2. (windows 2 and 3 are)");
|
|
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
|
if (hwnd == peasant1PID)
|
|
{
|
|
*result = false;
|
|
}
|
|
else if (hwnd == peasant2PID || hwnd == peasant3PID)
|
|
{
|
|
*result = true;
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
|
}
|
|
return S_OK;
|
|
};
|
|
manager->pfnIsWindowOnCurrentVirtualDesktop = thirdCallback;
|
|
|
|
Log::Comment(L"Summon window three - it is the MRU on desktop 2");
|
|
p1ExpectedToBeSummoned = false;
|
|
p2ExpectedToBeSummoned = false;
|
|
p3ExpectedToBeSummoned = true;
|
|
args.FoundMatch(false);
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Now we'll pretend we switched to desktop 1");
|
|
|
|
auto fourthCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
|
Log::Comment(L"fourthCallback: Checking if window is on desktop 1. (window 1 is)");
|
|
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
|
if (hwnd == peasant1PID)
|
|
{
|
|
*result = true;
|
|
}
|
|
else if (hwnd == peasant2PID || hwnd == peasant3PID)
|
|
{
|
|
*result = false;
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
|
}
|
|
return S_OK;
|
|
};
|
|
manager->pfnIsWindowOnCurrentVirtualDesktop = fourthCallback;
|
|
|
|
Log::Comment(L"Summon window one - it is the only window on desktop 1");
|
|
p1ExpectedToBeSummoned = true;
|
|
p2ExpectedToBeSummoned = false;
|
|
p3ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Now we'll pretend we switched to desktop 3");
|
|
|
|
auto fifthCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
|
Log::Comment(L"fifthCallback: Checking if window is on desktop 3. (none are)");
|
|
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
|
if (hwnd == peasant1PID || hwnd == peasant2PID || hwnd == peasant3PID)
|
|
{
|
|
*result = false;
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
|
}
|
|
return S_OK;
|
|
};
|
|
manager->pfnIsWindowOnCurrentVirtualDesktop = fifthCallback;
|
|
|
|
Log::Comment(L"This summon won't find a window.");
|
|
p1ExpectedToBeSummoned = false;
|
|
p2ExpectedToBeSummoned = false;
|
|
p3ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_FALSE(args.FoundMatch());
|
|
}
|
|
|
|
void RemotingTests::TestSummonOnCurrentWithName()
|
|
{
|
|
Log::Comment(L"Test that specifying a WindowName forces us to ignore OnCurrentDesktop");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
constexpr auto monarch0PID = 12345u;
|
|
constexpr auto peasant1PID = 23456u;
|
|
constexpr auto peasant2PID = 34567u;
|
|
constexpr auto peasant3PID = 45678u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
auto p3 = make_private<Remoting::implementation::Peasant>(peasant3PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
p3->WindowName(L"three");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
VERIFY_ARE_EQUAL(0, p3->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
m0->AddPeasant(*p3);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
VERIFY_ARE_EQUAL(3, p3->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(3u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
bool p3ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
p3->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p3 summoned");
|
|
VERIFY_IS_TRUE(p3ExpectedToBeSummoned);
|
|
});
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
p1->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
p2->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the third peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
p3->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
Log::Comment(L"Create a mock IVirtualDesktopManager to handle checking if a window is on a given desktop");
|
|
auto manager = winrt::make_self<MockDesktopManager>();
|
|
m0->_desktopManager = manager.try_as<IVirtualDesktopManager>();
|
|
|
|
auto firstCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
|
Log::Comment(L"firstCallback: Checking if window is on desktop 1");
|
|
|
|
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
|
if (hwnd == peasant1PID || hwnd == peasant3PID)
|
|
{
|
|
*result = true;
|
|
}
|
|
else if (hwnd == peasant2PID)
|
|
{
|
|
*result = false;
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
|
}
|
|
return S_OK;
|
|
};
|
|
manager->pfnIsWindowOnCurrentVirtualDesktop = firstCallback;
|
|
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
|
|
Log::Comment(L"Summon window three - it is the MRU on desktop 1");
|
|
p3ExpectedToBeSummoned = true;
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Look for window 1 by name. When given a name, we don't care about OnCurrentDesktop.");
|
|
p1ExpectedToBeSummoned = true;
|
|
p2ExpectedToBeSummoned = false;
|
|
p3ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.WindowName(L"one");
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Look for window 2 by name. When given a name, we don't care about OnCurrentDesktop.");
|
|
p1ExpectedToBeSummoned = false;
|
|
p2ExpectedToBeSummoned = true;
|
|
p3ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.WindowName(L"two");
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Look for window 3 by name. When given a name, we don't care about OnCurrentDesktop.");
|
|
p1ExpectedToBeSummoned = false;
|
|
p2ExpectedToBeSummoned = false;
|
|
p3ExpectedToBeSummoned = true;
|
|
args.FoundMatch(false);
|
|
args.WindowName(L"three");
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
}
|
|
|
|
void RemotingTests::TestSummonOnCurrentDeadWindow()
|
|
{
|
|
Log::Comment(L"Test that we can summon a window on the current desktop,"
|
|
L" when the MRU window on that desktop dies.");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
const winrt::guid guid2{ Utils::GuidFromString(L"{22222222-2222-2222-2222-222222222222}") };
|
|
|
|
constexpr auto monarch0PID = 12345u;
|
|
constexpr auto peasant1PID = 23456u;
|
|
constexpr auto peasant2PID = 34567u;
|
|
constexpr auto peasant3PID = 45678u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
auto p3 = make_private<Remoting::implementation::Peasant>(peasant3PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"two");
|
|
p3->WindowName(L"three");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
VERIFY_ARE_EQUAL(0, p3->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
m0->AddPeasant(*p3);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
VERIFY_ARE_EQUAL(3, p3->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(3u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
bool p3ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
p3->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p3 summoned");
|
|
VERIFY_IS_TRUE(p3ExpectedToBeSummoned);
|
|
});
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
p1->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the second peasant, second desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
p2->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid2,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the third peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p3->GetID(),
|
|
p3->GetPID(), // USE PID as HWND, because these values don't _really_ matter
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p3->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
Log::Comment(L"Create a mock IVirtualDesktopManager to handle checking if a window is on a given desktop");
|
|
auto manager = winrt::make_self<MockDesktopManager>();
|
|
m0->_desktopManager = manager.try_as<IVirtualDesktopManager>();
|
|
|
|
auto firstCallback = [&](HWND h, BOOL* result) -> HRESULT {
|
|
Log::Comment(L"firstCallback: Checking if window is on desktop 1");
|
|
|
|
const uint64_t hwnd = reinterpret_cast<uint64_t>(h);
|
|
if (hwnd == peasant1PID || hwnd == peasant3PID)
|
|
{
|
|
*result = true;
|
|
}
|
|
else if (hwnd == peasant2PID)
|
|
{
|
|
*result = false;
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(false, L"IsWindowOnCurrentVirtualDesktop called with unexpected value");
|
|
}
|
|
return S_OK;
|
|
};
|
|
manager->pfnIsWindowOnCurrentVirtualDesktop = firstCallback;
|
|
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
|
|
Log::Comment(L"Summon window three - it is the MRU on desktop 1");
|
|
p3ExpectedToBeSummoned = true;
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
|
|
Log::Comment(L"Kill window 3. Window 1 is now the MRU on desktop 1.");
|
|
RemotingTests::_killPeasant(m0, p3->GetID());
|
|
|
|
Log::Comment(L"Summon window three - it is the MRU on desktop 1");
|
|
p1ExpectedToBeSummoned = true;
|
|
p2ExpectedToBeSummoned = false;
|
|
p3ExpectedToBeSummoned = false;
|
|
args.FoundMatch(false);
|
|
args.OnCurrentDesktop(true);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
}
|
|
|
|
void RemotingTests::TestSummonMostRecentIsQuake()
|
|
{
|
|
Log::Comment(L"When a window is named _quake, it shouldn't participate "
|
|
L"in window glomming via the MRU window, but it should be able to be summoned");
|
|
|
|
const winrt::guid guid1{ Utils::GuidFromString(L"{11111111-1111-1111-1111-111111111111}") };
|
|
|
|
const auto monarch0PID = 12345u;
|
|
const auto peasant1PID = 23456u;
|
|
const auto peasant2PID = 34567u;
|
|
|
|
auto m0 = make_private<Remoting::implementation::Monarch>(monarch0PID);
|
|
auto p1 = make_private<Remoting::implementation::Peasant>(peasant1PID);
|
|
auto p2 = make_private<Remoting::implementation::Peasant>(peasant2PID);
|
|
|
|
p1->WindowName(L"one");
|
|
p2->WindowName(L"_quake");
|
|
|
|
VERIFY_ARE_EQUAL(0, p1->GetID());
|
|
VERIFY_ARE_EQUAL(0, p2->GetID());
|
|
|
|
m0->AddPeasant(*p1);
|
|
m0->AddPeasant(*p2);
|
|
|
|
VERIFY_ARE_EQUAL(1, p1->GetID());
|
|
VERIFY_ARE_EQUAL(2, p2->GetID());
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
|
|
|
|
bool p1ExpectedToBeSummoned = false;
|
|
bool p2ExpectedToBeSummoned = false;
|
|
|
|
p1->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p1 summoned");
|
|
VERIFY_IS_TRUE(p1ExpectedToBeSummoned);
|
|
});
|
|
p2->SummonRequested([&](auto&&, auto&&) {
|
|
Log::Comment(L"p2 summoned");
|
|
VERIFY_IS_TRUE(p2ExpectedToBeSummoned);
|
|
});
|
|
|
|
bool p1ExpectedCommandline = false;
|
|
bool p2ExpectedCommandline = false;
|
|
p1->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& /*cmdlineArgs*/) {
|
|
Log::Comment(L"Commandline dispatched to p1");
|
|
VERIFY_IS_TRUE(p1ExpectedCommandline);
|
|
});
|
|
p2->ExecuteCommandlineRequested([&](auto&&, const Remoting::CommandlineArgs& /*cmdlineArgs*/) {
|
|
Log::Comment(L"Commandline dispatched to p2");
|
|
VERIFY_IS_TRUE(p2ExpectedCommandline);
|
|
});
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
{
|
|
Log::Comment(L"Activate the first peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p1->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p1->ActivateWindow(activatedArgs);
|
|
}
|
|
{
|
|
Log::Comment(L"Activate the _quake peasant, first desktop");
|
|
Remoting::WindowActivatedArgs activatedArgs{ p2->GetID(),
|
|
guid1,
|
|
winrt::clock().now() };
|
|
p2->ActivateWindow(activatedArgs);
|
|
}
|
|
|
|
VERIFY_ARE_EQUAL(2u, m0->_mruPeasants.size());
|
|
VERIFY_ARE_EQUAL(p2->GetID(), m0->_mruPeasants[0].PeasantID());
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID());
|
|
|
|
std::vector<winrt::hstring> commandlineArgs{ L"0", L"arg[1]" };
|
|
Remoting::CommandlineArgs eventArgs{ { commandlineArgs }, { L"" } };
|
|
|
|
Log::Comment(L"When we attempt to send a commandline to the MRU window,"
|
|
L" we should find peasant 1 (who's name is \"one\"), not 2"
|
|
L" (who's name is \"_quake\")");
|
|
p1ExpectedCommandline = true;
|
|
p2ExpectedCommandline = false;
|
|
auto result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
|
|
{
|
|
Log::Comment(L"When we summon the MRU window, we'll still summon the _quake window");
|
|
p1ExpectedToBeSummoned = false;
|
|
p2ExpectedToBeSummoned = true;
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
args.OnCurrentDesktop(false);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
}
|
|
|
|
{
|
|
Log::Comment(L"rename p2 to \"two\"");
|
|
Remoting::RenameRequestArgs renameArgs{ L"two" };
|
|
p2->RequestRename(renameArgs);
|
|
VERIFY_IS_TRUE(renameArgs.Succeeded());
|
|
}
|
|
VERIFY_ARE_EQUAL(L"two", p2->WindowName());
|
|
|
|
Log::Comment(L"Now, the MRU window will correctly be p2, and we can glom to it");
|
|
p1ExpectedCommandline = false;
|
|
p2ExpectedCommandline = true;
|
|
result = m0->ProposeCommandline(eventArgs);
|
|
VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow());
|
|
VERIFY_ARE_EQUAL(false, (bool)result.Id());
|
|
|
|
{
|
|
Log::Comment(L"When we summon the MRU window, we'll still summon the window 2");
|
|
p1ExpectedToBeSummoned = false;
|
|
p2ExpectedToBeSummoned = true;
|
|
Remoting::SummonWindowSelectionArgs args;
|
|
args.OnCurrentDesktop(false);
|
|
m0->SummonWindow(args);
|
|
VERIFY_IS_TRUE(args.FoundMatch());
|
|
}
|
|
}
|
|
|
|
}
|