fb597ed304
## Summary of the Pull Request This PR adds support for renaming windows. ![window-renaming-000](https://user-images.githubusercontent.com/18356694/113034344-9a30be00-9157-11eb-9443-975f3c294f56.gif) ![window-renaming-001](https://user-images.githubusercontent.com/18356694/113034452-b5033280-9157-11eb-9e35-e5ac80fef0bc.gif) It does so through two new actions: * `renameWindow` takes a `name` parameter, and attempts to set the window's name to the provided name. This is useful if you always want to hit <kbd>F3</kbd> and rename a window to "foo" (READ: probably not that useful) * `openWindowRenamer` is more interesting: it opens a `TeachingTip` with a `TextBox`. When the user hits Ok, it'll request a rename for the provided value. This lets the user pick a new name for the window at runtime. In both cases, if there's already a window with that name, then the monarch will reject the rename, and pop a `Toast` in the window informing the user that the rename failed. Nifty! ## References * Builds on the toasts from #9523 * #5000 - process model megathread ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50771747 * [x] I work here * [x] Tests addded (and pass with the help of #9660) * [ ] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments I'm sending this PR while finishing up the tests. I figured I'll have time to sneak them in before I get the necessary reviews. > PAIN: We can't immediately focus the textbox in the TeachingTip. It's > not technically focusable until it is opened. However, it doesn't > provide an even tto tell us when it is opened. That's tracked in > microsoft/microsoft-ui-xaml#1607. So for now, the user _needs_ to > click on the text box manually. > We're also not using a ContentDialog for this, because in Xaml > Islands a text box in a ContentDialog won't recieve _any_ keypresses. > Fun! ## Validation Steps Performed I've been playing with ```json { "keys": "f1", "command": "identifyWindow" }, { "keys": "f2", "command": "identifyWindows" }, { "keys": "f3", "command": "openWindowRenamer" }, { "keys": "f4", "command": { "action": "renameWindow", "name": "foo" } }, { "keys": "f5", "command": { "action": "renameWindow", "name": "bar" } }, ``` and they seem to work as expected
1510 lines
62 KiB
C++
1510 lines
62 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;
|
|
|
|
// These are some gross macros that let us call a private ctor for
|
|
// Monarch/Peasant. We can't just use make_self, because that doesn't let us
|
|
// call a private ctor. We can use com_ptr::attach, but since we're allocating
|
|
// the thing on the stack, we need to make sure to call detach before the object
|
|
// is destructed.
|
|
|
|
#define MAKE_MONARCH(name, pid) \
|
|
Remoting::implementation::Monarch _local_##name##{ pid }; \
|
|
com_ptr<Remoting::implementation::Monarch> name; \
|
|
name.attach(&_local_##name##); \
|
|
auto cleanup_##name## = wil::scope_exit([&]() { name.detach(); });
|
|
|
|
#define MAKE_PEASANT(name, pid) \
|
|
Remoting::implementation::Peasant _local_##name##{ pid }; \
|
|
com_ptr<Remoting::implementation::Peasant> name; \
|
|
name.attach(&_local_##name##); \
|
|
auto cleanup_##name## = wil::scope_exit([&]() { name.detach(); });
|
|
|
|
namespace RemotingUnitTests
|
|
{
|
|
// 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{}; }
|
|
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);
|
|
};
|
|
|
|
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(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_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);
|
|
};
|
|
|
|
// 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;
|
|
}
|
|
|
|
com_ptr<DeadPeasant> tombstone;
|
|
tombstone.attach(new DeadPeasant());
|
|
m->_peasants[peasantID] = *tombstone;
|
|
}
|
|
|
|
// 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 = winrt::make_self<Remoting::implementation::Monarch>();
|
|
VERIFY_IS_NOT_NULL(m1);
|
|
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;
|
|
MAKE_MONARCH(m2, expectedFakePID);
|
|
|
|
VERIFY_IS_NOT_NULL(m2);
|
|
VERIFY_ARE_EQUAL(expectedFakePID,
|
|
m2->GetPID(),
|
|
L"A Monarch with an explicit PID should use the one we provided");
|
|
}
|
|
|
|
void RemotingTests::CreatePeasant()
|
|
{
|
|
auto p1 = winrt::make_self<Remoting::implementation::Peasant>();
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
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;
|
|
MAKE_PEASANT(p2, expectedFakePID);
|
|
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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 = winrt::make_self<Remoting::implementation::Peasant>();
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_ARE_EQUAL(GetCurrentProcessId(),
|
|
p1->GetPID(),
|
|
L"A Peasant without an explicit PID should use the current PID");
|
|
|
|
auto expectedFakePID = 2345u;
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
VERIFY_IS_NULL(p2);
|
|
p2.attach(new Remoting::implementation::Peasant(expectedFakePID));
|
|
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
|
|
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_IS_NOT_NULL(maybeP1);
|
|
VERIFY_ARE_EQUAL(peasant1PID, maybeP1.GetPID());
|
|
|
|
auto maybeP2 = m0->_getPeasant(2);
|
|
VERIFY_IS_NOT_NULL(maybeP2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m3;
|
|
m3.attach(new Remoting::implementation::Monarch(monarch3PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
VERIFY_IS_NOT_NULL(m3);
|
|
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
|
|
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_IS_NOT_NULL(maybeP2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
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;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
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;
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
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;
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
com_ptr<Remoting::implementation::Peasant> p3;
|
|
p3.attach(new Remoting::implementation::Peasant(peasant3PID));
|
|
VERIFY_IS_NOT_NULL(p3);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
com_ptr<Remoting::implementation::Peasant> p3;
|
|
p3.attach(new Remoting::implementation::Peasant(peasant3PID));
|
|
VERIFY_IS_NOT_NULL(p3);
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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));
|
|
|
|
Log::Comment(L"Add a third peasant");
|
|
const auto peasant3PID = 45678u;
|
|
com_ptr<Remoting::implementation::Peasant> p3;
|
|
p3.attach(new Remoting::implementation::Peasant(peasant3PID));
|
|
VERIFY_IS_NOT_NULL(p3);
|
|
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));
|
|
|
|
{
|
|
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));
|
|
}
|
|
|
|
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;
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper);
|
|
|
|
Log::Comment(L"Add a peasant");
|
|
const auto peasant1PID = 23456u;
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
m0->AddPeasant(*p1);
|
|
|
|
Log::Comment(L"Add a second peasant");
|
|
const auto peasant2PID = 34567u;
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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));
|
|
|
|
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::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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m3;
|
|
m3.attach(new Remoting::implementation::Monarch(monarch3PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
VERIFY_IS_NOT_NULL(m3);
|
|
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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));
|
|
VERIFY_ARE_EQUAL(p1->GetID(), m0->_getMostRecentPeasantID(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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowByNameHelper);
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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;
|
|
|
|
com_ptr<Remoting::implementation::Monarch> m0;
|
|
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p1;
|
|
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
|
|
|
|
com_ptr<Remoting::implementation::Peasant> p2;
|
|
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
|
|
|
|
VERIFY_IS_NOT_NULL(m0);
|
|
VERIFY_IS_NOT_NULL(p1);
|
|
VERIFY_IS_NOT_NULL(p2);
|
|
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"));
|
|
}
|
|
|
|
}
|