chore: import upstream snapshot with attribution
Spell checking / Check Spelling (push) Has been cancelled
Spell checking / Update PR (push) Has been cancelled
Publish Dev Docs Website / build (push) Failing after 1s
Publish Dev Docs Website / deploy (push) Has been skipped
Spell checking / Report (Push) (push) Has been cancelled
Spell checking / Report (PR) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:16:02 +08:00
commit 79031da543
8235 changed files with 1365916 additions and 0 deletions
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp build" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
<Identity Name="3b548ab3-3034-4edf-a625-4691c73b43a9" Publisher="CN=divyan" Version="1.0.0.0" ProcessorArchitecture="x86" />
<mp:PhoneIdentity PhoneProductId="3b548ab3-3034-4edf-a625-4691c73b43a9" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>DevelopmentApp</DisplayName>
<PublisherDisplayName>divyan</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.19041.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27810.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.NET.CoreRuntime.2.2" MinVersion="2.2.27902.3" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.NET.CoreFramework.Debug.2.2" MinVersion="2.2.27909.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>
<Resources>
<Resource Language="EN-US" />
</Resources>
<Applications>
<Application Id="App" Executable="DevelopmentApp.exe" EntryPoint="DevelopmentApp.App">
<uap:VisualElements DisplayName="DevelopmentApp" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="DevelopmentApp" BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>DevelopmentApp.exe</Path>
<ActivatableClass ActivatableClassId="Microsoft.UI.Xaml.Markup.ReflectionXamlMetadataProvider" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
<build:Metadata>
<build:Item Name="TargetFrameworkMoniker" Value=".NETCore,Version=v5.0" />
<build:Item Name="VisualStudio" Version="16.0" />
<build:Item Name="VisualStudioEdition" Value="Microsoft Visual Studio Enterprise 2019" />
<build:Item Name="OperatingSystem" Version="10.0.18362.1 (WinBuild.160101.0800)" />
<build:Item Name="Microsoft.Build.AppxPackage.dll" Version="16.0.30009.100" />
<build:Item Name="ProjectGUID" Value="{A995B1F6-B462-4CC0-8E7F-3C9A9354A700}" />
<build:Item Name="OptimizingToolset" Value="None" />
<build:Item Name="TargetRuntime" Value="Managed" />
<build:Item Name="Microsoft.Windows.UI.Xaml.Build.Tasks.dll" Version="10.0.18362.1" />
<build:Item Name="MakePri.exe" Version="10.0.18362.1 (WinBuild.160101.0800)" />
</build:Metadata>
</Package>
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp build" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
<Identity Name="3b548ab3-3034-4edf-a625-4691c73b43a9" Publisher="CN=divyan" Version="1.0.0.0" ProcessorArchitecture="x86" />
<mp:PhoneIdentity PhoneProductId="3b548ab3-3034-4edf-a625-4691c73b43a9" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>FrameworkApp</DisplayName>
<PublisherDisplayName>divyan</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.19041.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27810.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.NET.CoreRuntime.2.2" MinVersion="2.2.27902.3" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.NET.CoreFramework.Debug.2.2" MinVersion="2.2.27909.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>
<Resources>
<Resource Language="EN-US" />
</Resources>
<Applications>
<Application Id="App" Executable="FrameworkApp.exe" EntryPoint="FrameworkApp.App">
<uap:VisualElements DisplayName="FrameworkApp" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="FrameworkApp" BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>FrameworkApp.exe</Path>
<ActivatableClass ActivatableClassId="Microsoft.UI.Xaml.Markup.ReflectionXamlMetadataProvider" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
<build:Metadata>
<build:Item Name="TargetFrameworkMoniker" Value=".NETCore,Version=v5.0" />
<build:Item Name="VisualStudio" Version="16.0" />
<build:Item Name="VisualStudioEdition" Value="Microsoft Visual Studio Enterprise 2019" />
<build:Item Name="OperatingSystem" Version="10.0.18362.1 (WinBuild.160101.0800)" />
<build:Item Name="Microsoft.Build.AppxPackage.dll" Version="16.0.30009.100" />
<build:Item Name="ProjectGUID" Value="{A995B1F6-B462-4CC0-8E7F-3C9A9354A700}" />
<build:Item Name="OptimizingToolset" Value="None" />
<build:Item Name="TargetRuntime" Value="Managed" />
<build:Item Name="Microsoft.Windows.UI.Xaml.Build.Tasks.dll" Version="10.0.18362.1" />
<build:Item Name="MakePri.exe" Version="10.0.18362.1 (WinBuild.160101.0800)" />
</build:Metadata>
</Package>
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp build" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
<Identity Name="3b548ab3-3034-4edf-a625-4691c73b43a9" Publisher="CN=divyan" Version="1.0.0.0" ProcessorArchitecture="x86" />
<mp:PhoneIdentity PhoneProductId="3b548ab3-3034-4edf-a625-4691c73b43a9" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>PackagedApp</DisplayName>
<PublisherDisplayName>divyan</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.19041.0" MaxVersionTested="10.0.19041.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27810.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.NET.CoreRuntime.2.2" MinVersion="2.2.27902.3" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.NET.CoreFramework.Debug.2.2" MinVersion="2.2.27909.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>
<Resources>
<Resource Language="EN-US" />
</Resources>
<Applications>
<Application Id="App" Executable="PackagedApp.exe" EntryPoint="PackagedApp.App">
<uap:VisualElements DisplayName="PackagedApp" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="PackagedApp" BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>PackagedApp.exe</Path>
<ActivatableClass ActivatableClassId="Microsoft.UI.Xaml.Markup.ReflectionXamlMetadataProvider" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
<build:Metadata>
<build:Item Name="TargetFrameworkMoniker" Value=".NETCore,Version=v5.0" />
<build:Item Name="VisualStudio" Version="16.0" />
<build:Item Name="VisualStudioEdition" Value="Microsoft Visual Studio Enterprise 2019" />
<build:Item Name="OperatingSystem" Version="10.0.18362.1 (WinBuild.160101.0800)" />
<build:Item Name="Microsoft.Build.AppxPackage.dll" Version="16.0.30009.100" />
<build:Item Name="ProjectGUID" Value="{A995B1F6-B462-4CC0-8E7F-3C9A9354A700}" />
<build:Item Name="OptimizingToolset" Value="None" />
<build:Item Name="TargetRuntime" Value="Managed" />
<build:Item Name="Microsoft.Windows.UI.Xaml.Build.Tasks.dll" Version="10.0.18362.1" />
<build:Item Name="MakePri.exe" Version="10.0.18362.1 (WinBuild.160101.0800)" />
</build:Metadata>
</Package>
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Look at Directory.Build.props in root for common stuff as well -->
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Moq" />
<PackageReference Include="MSTest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Plugin.Program\Microsoft.Plugin.Program.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="AppxManifests\DevelopmentApp\AppxManifest.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="AppxManifests\FrameworkApp\AppxManifest.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="AppxManifests\PackagedApp\AppxManifest.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Plugin.Program.ProgramArgumentParser;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wox.Plugin;
namespace Microsoft.Plugin.Program.UnitTests.ProgramArgumentParser
{
[TestClass]
public class ProgramArgumentParserTests
{
[DataTestMethod]
[DataRow("Microsoft Edge", "Microsoft Edge", null)]
[DataRow("Microsoft Edge ---inprivate", "Microsoft Edge ---inprivate", null)]
[DataRow("Microsoft Edge -- -inprivate", "Microsoft Edge", "-inprivate")]
[DataRow("Microsoft Edge -inprivate", "Microsoft Edge", "-inprivate")]
[DataRow("Microsoft Edge /inprivate", "Microsoft Edge", "/inprivate")]
[DataRow("edge.exe --inprivate", "edge.exe", "--inprivate")]
[DataRow("edge.exe -- --inprivate", "edge.exe", "--inprivate")]
[DataRow("edge.exe", "edge.exe", null)]
[DataRow("edge", "edge", null)]
[DataRow("cmd /c \"ping 1.1.1.1\"", "cmd", "/c \"ping 1.1.1.1\"")]
public void ProgramArgumentParserTestsCanParseQuery(string inputQuery, string expectedProgram, string expectedProgramArguments)
{
// Arrange
var argumentParsers = new IProgramArgumentParser[]
{
new DoubleDashProgramArgumentParser(),
new InferredProgramArgumentParser(),
new NoArgumentsArgumentParser(),
};
var query = new Query(inputQuery);
// Act
string program = null, programArguments = null;
foreach (var argumentParser in argumentParsers)
{
if (argumentParser.TryParse(query, out program, out programArguments))
{
break;
}
}
// Assert
Assert.AreEqual(expectedProgram, program);
Assert.AreEqual(expectedProgramArguments, programArguments);
}
}
}
@@ -0,0 +1,97 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using Castle.Core.Internal;
using Microsoft.Plugin.Program.Programs;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace Microsoft.Plugin.Program.UnitTests.Programs
{
[TestClass]
public class UWPTests
{
private static readonly PackageWrapper DevelopmentModeApp = new PackageWrapper(
"DevelopmentApp",
"DevelopmentApp",
"DevelopmentApp",
false,
true,
"AppxManifests/DevelopmentApp");
private static readonly PackageWrapper FrameworkApp = new PackageWrapper(
"FrameworkApp",
"FrameworkApp",
"FrameworkApp",
true,
false,
"AppxManifests/FrameworkApp");
private static readonly PackageWrapper PackagedApp = new PackageWrapper(
"PackagedApp",
"PackagedApp",
"PackagedApp",
false,
false,
"AppxManifests/PackagedApp");
[TestMethod]
public void AllShouldReturnPackagesWithDevelopmentModeWhenCalled()
{
// Arrange
Main.Settings = new ProgramPluginSettings();
List<IPackage> packages = new List<IPackage>() { DevelopmentModeApp, PackagedApp };
var mock = new Mock<IPackageManager>();
mock.Setup(x => x.FindPackagesForCurrentUser()).Returns(packages);
UWP.PackageManagerWrapper = mock.Object;
// Act
var applications = UWP.All();
// Assert
Assert.AreEqual(2, applications.Length);
Assert.IsTrue(Array.FindAll(applications, x => x.Name == "DevelopmentApp").Length > 0);
Assert.IsTrue(Array.FindAll(applications, x => x.Name == "PackagedApp").Length > 0);
}
[TestMethod]
public void AllShouldNotReturnPackageFrameworksWhenCalled()
{
// Arrange
Main.Settings = new ProgramPluginSettings();
List<IPackage> packages = new List<IPackage>() { FrameworkApp, PackagedApp };
var mock = new Mock<IPackageManager>();
mock.Setup(x => x.FindPackagesForCurrentUser()).Returns(packages);
UWP.PackageManagerWrapper = mock.Object;
// Act
var applications = UWP.All();
// Assert
Assert.AreEqual(1, applications.Length);
Assert.IsTrue(Array.FindAll(applications, x => x.Name == "PackagedApp").Length > 0);
}
[TestMethod]
public void PowerToysRunShouldNotAddInvalidAppWhenIndexingUWPApplications()
{
// Arrange
PackageWrapper invalidPackagedApp = new PackageWrapper();
Main.Settings = new ProgramPluginSettings();
List<IPackage> packages = new List<IPackage>() { invalidPackagedApp };
var mock = new Mock<IPackageManager>();
mock.Setup(x => x.FindPackagesForCurrentUser()).Returns(packages);
UWP.PackageManagerWrapper = mock.Object;
// Act
var applications = UWP.All();
// Assert
Assert.AreEqual(0, applications.Length);
}
}
}
@@ -0,0 +1,654 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Wox.Infrastructure;
using Wox.Infrastructure.FileSystemHelper;
using Wox.Plugin;
using Win32Program = Microsoft.Plugin.Program.Programs.Win32Program;
namespace Microsoft.Plugin.Program.UnitTests.Programs
{
[TestClass]
public class Win32Tests
{
private static readonly Win32Program _imagingDevices = new Win32Program
{
Name = "Imaging Devices",
ExecutableName = "imagingdevices.exe",
FullPath = "c:\\program files\\windows photo viewer\\imagingdevices.exe",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _notepadAppdata = new Win32Program
{
Name = "Notepad",
ExecutableName = "notepad.exe",
FullPath = "c:\\windows\\system32\\notepad.exe",
LnkFilePath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\accessories\\notepad.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _notepadUsers = new Win32Program
{
Name = "Notepad",
ExecutableName = "notepad.exe",
FullPath = "c:\\windows\\system32\\notepad.exe",
LnkFilePath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\accessories\\notepad.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _azureCommandPrompt = new Win32Program
{
Name = "Microsoft Azure Command Prompt - v2.9",
ExecutableName = "cmd.exe",
FullPath = "c:\\windows\\system32\\cmd.exe",
Arguments = @"/E:ON /V:ON /K ""C:\Program Files\Microsoft SDKs\Azure\.NET SDK\v2.9\\bin\setenv.cmd""",
LnkFilePath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\microsoft azure\\microsoft azure sdk for .net\\v2.9\\microsoft azure command prompt - v2.9.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _visualStudioCommandPrompt = new Win32Program
{
Name = "x64 Native Tools Command Prompt for VS 2019",
ExecutableName = "cmd.exe",
FullPath = "c:\\windows\\system32\\cmd.exe",
Arguments = @"/k ""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat""",
LnkFilePath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\visual studio 2019\\visual studio tools\\vc\\x64 native tools command prompt for vs 2019.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _commandPrompt = new Win32Program
{
Name = "Command Prompt",
ExecutableName = "cmd.exe",
FullPath = "c:\\windows\\system32\\cmd.exe",
LnkFilePath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\system tools\\command prompt.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _fileExplorerLink = new Win32Program
{
Name = "File Explorer",
ExecutableName = "File Explorer.lnk",
FullPath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\system tools\\file explorer.lnk",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _fileExplorer = new Win32Program
{
Name = "File Explorer",
ExecutableName = "explorer.exe",
FullPath = "c:\\windows\\explorer.exe",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _wordpad = new Win32Program
{
Name = "Wordpad",
ExecutableName = "wordpad.exe",
FullPath = "c:\\program files\\windows nt\\accessories\\wordpad.exe",
LnkFilePath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\accessories\\wordpad.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _wordpadDuplicate = new Win32Program
{
Name = "WORDPAD",
ExecutableName = "WORDPAD.EXE",
FullPath = "c:\\program files\\windows nt\\accessories\\wordpad.exe",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _twitterChromePwa = new Win32Program
{
Name = "Twitter",
FullPath = "c:\\program files (x86)\\google\\chrome\\application\\chrome_proxy.exe",
LnkFilePath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\chrome apps\\twitter.lnk",
Arguments = " --profile-directory=Default --app-id=jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi",
AppType = 0,
};
private static readonly Win32Program _pinnedWebpage = new Win32Program
{
Name = "Web page",
FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\msedge_proxy.exe",
LnkFilePath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\web page.lnk",
Arguments = "--profile-directory=Default --app-id=homljgmgpmcbpjbnjpfijnhipfkiclkd",
AppType = 0,
};
private static readonly Win32Program _edgeNamedPinnedWebpage = new Win32Program
{
Name = "edge - Bing",
FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\msedge_proxy.exe",
LnkFilePath = "c:\\users\\powertoys\\appdata\\roaming\\microsoft\\windows\\start menu\\programs\\edge - bing.lnk",
Arguments = " --profile-directory=Default --app-id=aocfnapldcnfbofgmbbllojgocaelgdd",
AppType = 0,
};
private static readonly Win32Program _msedge = new Win32Program
{
Name = "Microsoft Edge",
ExecutableName = "msedge.exe",
FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\msedge.exe",
LnkFilePath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\microsoft edge.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _chrome = new Win32Program
{
Name = "Google Chrome",
ExecutableName = "chrome.exe",
FullPath = "c:\\program files (x86)\\google\\chrome\\application\\chrome.exe",
LnkFilePath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\google chrome.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _dummyProxyApp = new Win32Program
{
Name = "Proxy App",
ExecutableName = "test_proxy.exe",
FullPath = "c:\\program files (x86)\\microsoft\\edge\\application\\test_proxy.exe",
LnkFilePath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\test proxy.lnk",
AppType = Win32Program.ApplicationType.Win32Application,
};
private static readonly Win32Program _cmdRunCommand = new Win32Program
{
Name = "cmd",
ExecutableName = "cmd.exe",
FullPath = "c:\\windows\\system32\\cmd.exe",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.RunCommand, // Run command
};
private static readonly Win32Program _cmderRunCommand = new Win32Program
{
Name = "Cmder",
Description = "Cmder: Lovely Console Emulator",
ExecutableName = "Cmder.exe",
FullPath = "c:\\tools\\cmder\\cmder.exe",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.RunCommand, // Run command
};
private static readonly Win32Program _dummyInternetShortcutApp = new Win32Program
{
Name = "Shop Titans",
ExecutableName = "Shop Titans.url",
FullPath = "steam://rungameid/1258080",
ParentDirectory = "C:\\Users\\temp\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Steam",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.InternetShortcutApplication,
};
private static readonly Win32Program _dummyInternetShortcutAppDuplicate = new Win32Program
{
Name = "Shop Titans",
ExecutableName = "Shop Titans.url",
FullPath = "steam://rungameid/1258080",
ParentDirectory = "C:\\Users\\temp\\Desktop",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.InternetShortcutApplication,
};
private static readonly Win32Program _dummyAppRefApp = new Win32Program
{
Name = "Dummy AppRef Application",
ExecutableName = "dummy.appref-ms",
FullPath = "C:\\dummy.appref-ms",
ParentDirectory = "C:\\",
LnkFilePath = null,
AppType = Win32Program.ApplicationType.ApprefApplication,
};
private static readonly Win32Program _dummyShortcutApp = new Win32Program
{
Name = "Dummy Shortcut Application",
ExecutableName = "application.lnk",
FullPath = "C:\\application.lnk",
ParentDirectory = "C:\\",
LnkFilePath = "C:\\application.lnk",
AppType = Win32Program.ApplicationType.ShortcutApplication,
};
private static readonly Win32Program _dummyFolderApp = new Win32Program
{
Name = "Dummy Folder",
ExecutableName = "application.lnk",
FullPath = "C:\\dummy\\folder",
ParentDirectory = "C:\\dummy\\",
LnkFilePath = "C:\\tools\\application.lnk",
AppType = Win32Program.ApplicationType.Folder,
};
private static readonly Win32Program _dummyGenericFileApp = new Win32Program
{
Name = "Dummy Folder",
ExecutableName = "application.lnk",
FullPath = "C:\\dummy\\file.pdf",
ParentDirectory = "C:\\dummy\\",
LnkFilePath = "C:\\tools\\application.lnk",
AppType = Win32Program.ApplicationType.GenericFile,
};
private static IDirectoryWrapper GetMockedDirectoryWrapper()
{
var mockDirectory = new Mock<IDirectoryWrapper>();
// Check if the file has no extension. This is not actually true since there can be files without extensions, but this is sufficient for the purpose of a mock function
Func<string, bool> returnValue = arg => string.IsNullOrEmpty(System.IO.Path.GetExtension(arg));
mockDirectory.Setup(m => m.Exists(It.IsAny<string>())).Returns(returnValue);
return mockDirectory.Object;
}
[TestMethod]
public void DedupFunctionWhenCalledMustRemoveDuplicateNotepads()
{
// Arrange
List<Win32Program> prgms = new List<Win32Program>
{
_notepadAppdata,
_notepadUsers,
};
// Act
List<Win32Program> apps = Win32Program.DeduplicatePrograms(prgms.AsParallel());
// Assert
Assert.AreEqual(1, apps.Count);
}
[TestMethod]
public void DedupFunctionWhenCalledMustRemoveInternetShortcuts()
{
// Arrange
List<Win32Program> prgms = new List<Win32Program>
{
_dummyInternetShortcutApp,
_dummyInternetShortcutAppDuplicate,
};
// Act
List<Win32Program> apps = Win32Program.DeduplicatePrograms(prgms.AsParallel());
// Assert
Assert.AreEqual(1, apps.Count);
}
[TestMethod]
public void DedupFunctionWhenCalledMustNotRemovelnkWhichDoesNotHaveExe()
{
// Arrange
List<Win32Program> prgms = new List<Win32Program>
{
_fileExplorerLink,
};
// Act
List<Win32Program> apps = Win32Program.DeduplicatePrograms(prgms.AsParallel());
// Assert
Assert.AreEqual(1, apps.Count);
}
[TestMethod]
public void DedupFunctionMustRemoveDuplicatesForExeExtensionsWithoutLnkFilePath()
{
// Arrange
List<Win32Program> prgms = new List<Win32Program>
{
_wordpad,
_wordpadDuplicate,
};
// Act
List<Win32Program> apps = Win32Program.DeduplicatePrograms(prgms.AsParallel());
// Assert
Assert.AreEqual(1, apps.Count);
Assert.IsTrue(!string.IsNullOrEmpty(apps[0].LnkFilePath));
}
[TestMethod]
public void DedupFunctionMustNotRemoveProgramsWithSameExeNameAndFullPath()
{
// Arrange
List<Win32Program> prgms = new List<Win32Program>
{
_azureCommandPrompt,
_visualStudioCommandPrompt,
_commandPrompt,
};
// Act
List<Win32Program> apps = Win32Program.DeduplicatePrograms(prgms.AsParallel());
// Assert
Assert.AreEqual(3, apps.Count);
}
[TestMethod]
public void FunctionIsWebApplicationShouldReturnTrueForWebApplications()
{
// The IsWebApplication(() function must return true for all PWAs and pinned web pages
Assert.IsTrue(_twitterChromePwa.IsWebApplication());
Assert.IsTrue(_pinnedWebpage.IsWebApplication());
Assert.IsTrue(_edgeNamedPinnedWebpage.IsWebApplication());
// Should not filter apps whose executable name ends with proxy.exe
Assert.IsFalse(_dummyProxyApp.IsWebApplication());
}
[DataTestMethod]
[DataRow("ignore")]
public void FunctionFilterWebApplicationShouldReturnFalseWhenSearchingForTheMainApp(string query)
{
// Irrespective of the query, the FilterWebApplication() Function must not filter main apps such as edge and chrome
Assert.IsFalse(_msedge.FilterWebApplication(query));
Assert.IsFalse(_chrome.FilterWebApplication(query));
}
[DataTestMethod]
[DataRow("edge", true)]
[DataRow("EDGE", true)]
[DataRow("msedge", true)]
[DataRow("Microsoft", true)]
[DataRow("edg", true)]
[DataRow("Edge page", false)]
[DataRow("Edge Web page", false)]
public void EdgeWebSitesShouldBeFilteredWhenSearchingForEdge(string query, bool result)
{
Assert.AreEqual(_pinnedWebpage.FilterWebApplication(query), result);
}
[DataTestMethod]
[DataRow("chrome", true)]
[DataRow("CHROME", true)]
[DataRow("Google", true)]
[DataRow("Google Chrome", true)]
[DataRow("Google Chrome twitter", false)]
public void ChromeWebSitesShouldBeFilteredWhenSearchingForChrome(string query, bool result)
{
Assert.AreEqual(_twitterChromePwa.FilterWebApplication(query), result);
}
[DataTestMethod]
[DataRow("twitter", 0, false)]
[DataRow("Twit", 0, false)]
[DataRow("TWITTER", 0, false)]
[DataRow("web", 1, false)]
[DataRow("Page", 1, false)]
[DataRow("WEB PAGE", 1, false)]
[DataRow("edge", 2, false)]
[DataRow("EDGE", 2, false)]
public void PinnedWebPagesShouldNotBeFilteredWhenSearchingForThem(string query, int scenario, bool result)
{
const int CASE_TWITTER = 0;
const int CASE_WEB_PAGE = 1;
const int CASE_EDGE_NAMED_WEBPAGE = 2;
// If the query is a part of the name of the web application, it should not be filtered,
// even if the name is the same as that of the main application, eg: case 2 - edge
switch (scenario)
{
case CASE_TWITTER:
Assert.AreEqual(_twitterChromePwa.FilterWebApplication(query), result);
return;
case CASE_WEB_PAGE:
Assert.AreEqual(_pinnedWebpage.FilterWebApplication(query), result);
return;
case CASE_EDGE_NAMED_WEBPAGE:
Assert.AreEqual(_edgeNamedPinnedWebpage.FilterWebApplication(query), result);
return;
default:
break;
}
}
[DataTestMethod]
[DataRow("Command Prompt")]
[DataRow("cmd")]
[DataRow("cmd.exe")]
[DataRow("ignoreQueryText")]
public void Win32ApplicationsShouldNotBeFilteredWhenFilteringRunCommands(string query)
{
// Even if there is an exact match in the name or exe name, win32 applications should never be filtered
Assert.IsTrue(_commandPrompt.QueryEqualsNameForRunCommands(query));
}
[DataTestMethod]
[DataRow("explorer")]
[DataRow("explorer.exe")]
public void Win32ApplicationsShouldNotFilterWhenExecutingNameOrNameIsUsed(string query)
{
// Even if there is an exact match in the name or exe name, win32 applications should never be filtered
Assert.IsTrue(_fileExplorer.QueryEqualsNameForRunCommands(query));
}
[DataTestMethod]
[DataRow("cmd")]
[DataRow("Cmd")]
[DataRow("CMD")]
public void RunCommandsShouldNotBeFilteredOnExactMatch(string query)
{
// Partial matches should be filtered as cmd is not equal to cmder
Assert.IsFalse(_cmderRunCommand.QueryEqualsNameForRunCommands(query));
// the query matches the name (cmd) and is therefore not filtered (case-insensitive)
Assert.IsTrue(_cmdRunCommand.QueryEqualsNameForRunCommands(query));
}
[DataTestMethod]
[DataRow("ımaging")]
public void Win32ApplicationsShouldNotHaveIncorrectPathWhenExecuting(string query)
{
Assert.IsFalse(_imagingDevices.FullPath.Contains(query, StringComparison.Ordinal));
}
[TestMethod]
public void WebApplicationShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _pinnedWebpage.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(4, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_administrator, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_user, contextMenuResults[1].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[2].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[3].Title);
}
[TestMethod]
public void InternetShortcutApplicationShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _dummyInternetShortcutApp.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(2, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[1].Title);
}
[TestMethod]
public void Win32ApplicationShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _chrome.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(4, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_administrator, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_user, contextMenuResults[1].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[2].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[3].Title);
}
[TestMethod]
public void RunCommandShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _cmdRunCommand.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(4, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_administrator, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_user, contextMenuResults[1].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[2].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[3].Title);
}
[TestMethod]
public void AppRefApplicationShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _dummyAppRefApp.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(4, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_administrator, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_user, contextMenuResults[1].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[2].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[3].Title);
}
[TestMethod]
public void ShortcutApplicationShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _dummyShortcutApp.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(4, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_administrator, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_run_as_user, contextMenuResults[1].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[2].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[3].Title);
}
[TestMethod]
public void FolderApplicationShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _dummyFolderApp.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(2, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[1].Title);
}
[TestMethod]
public void GenericFileApplicationShouldReturnContextMenuWithOpenInConsoleWhenContextMenusIsCalled()
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _dummyGenericFileApp.ContextMenus(string.Empty, mock.Object);
// Assert
Assert.AreEqual(2, contextMenuResults.Count);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_containing_folder, contextMenuResults[0].Title);
Assert.AreEqual(Properties.Resources.wox_plugin_program_open_in_console, contextMenuResults[1].Title);
}
[TestMethod]
public void Win32AppsShouldSetNameAsTitleWhileCreatingResult()
{
var mock = new Mock<IPublicAPI>();
StringMatcher.Instance = new StringMatcher();
// Act
var result = _chrome.Result("chrome", string.Empty, mock.Object);
// Assert
// Using Ordinal since this is used internally
Assert.IsTrue(result.Title.Equals(_chrome.Name, StringComparison.Ordinal));
Assert.IsFalse(result.Title.Equals(_chrome.Description, StringComparison.Ordinal));
}
[TestMethod]
public void RunCommandsShouldSetExecutableNameAsTitleWhileCreatingResult()
{
var mock = new Mock<IPublicAPI>();
StringMatcher.Instance = new StringMatcher();
// Act
var result = _cmderRunCommand.Result("cmder", string.Empty, mock.Object);
// Assert
// Using Ordinal since this is used internally
Assert.IsTrue(result.Title.Equals(_cmderRunCommand.ExecutableName, StringComparison.Ordinal));
Assert.IsFalse(result.Title.Equals(_cmderRunCommand.Description, StringComparison.Ordinal));
}
[DataTestMethod]
[DataRow("C:\\Program Files\\dummy.exe", Win32Program.ApplicationType.Win32Application)]
[DataRow("C:\\Program Files\\dummy.msc", Win32Program.ApplicationType.Win32Application)]
[DataRow("C:\\Program Files\\dummy.lnk", Win32Program.ApplicationType.ShortcutApplication)]
[DataRow("C:\\Program Files\\dummy.appref-ms", Win32Program.ApplicationType.ApprefApplication)]
[DataRow("C:\\Program Files\\dummy.url", Win32Program.ApplicationType.InternetShortcutApplication)]
[DataRow("C:\\Program Files\\dummy", Win32Program.ApplicationType.Folder)]
[DataRow("C:\\Program Files\\dummy.txt", Win32Program.ApplicationType.GenericFile)]
public void GetAppTypeFromPathShouldReturnCorrectAppTypeWhenAppPathIsPassedAsArgument(string path, Win32Program.ApplicationType result)
{
// Directory.Exists must be mocked
Win32Program.DirectoryWrapper = GetMockedDirectoryWrapper();
// Act
Assert.AreEqual(Win32Program.GetAppTypeFromPath(path), result);
}
[DataTestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow("ping 1.1.1.1")]
public void EmptyArgumentsShouldNotThrow(string argument)
{
// Arrange
var mock = new Mock<IPublicAPI>();
// Act
List<ContextMenuResult> contextMenuResults = _dummyInternetShortcutApp.ContextMenus(argument, mock.Object);
// Assert (Should always return if the above does not throw any exception)
Assert.IsTrue(true);
}
}
}
@@ -0,0 +1,112 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Microsoft.Plugin.Program.Storage;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.Plugin.Program.UnitTests.Storage
{
[TestClass]
public class ConcurrentQueueEventHandlerTest
{
[DataTestMethod]
[DataRow]
public async Task EventHandlerMustReturnEmptyPathForEmptyQueueAsync()
{
// Arrange
int dequeueDelay = 0;
ConcurrentQueue<string> eventHandlingQueue = new ConcurrentQueue<string>();
// Act
string appPath = await EventHandler.GetAppPathFromQueueAsync(eventHandlingQueue, dequeueDelay).ConfigureAwait(false);
// Assert
Assert.IsTrue(string.IsNullOrEmpty(appPath));
}
[DataTestMethod]
[DataRow(1)]
[DataRow(10)]
public async Task EventHandlerMustReturnPathForConcurrentQueueWithSameFilePathsAsync(int itemCount)
{
// Arrange
int dequeueDelay = 0;
string appPath = "appPath";
ConcurrentQueue<string> eventHandlingQueue = new ConcurrentQueue<string>();
for (int i = 0; i < itemCount; i++)
{
eventHandlingQueue.Enqueue(appPath);
}
// Act
string pathFromQueue = await EventHandler.GetAppPathFromQueueAsync(eventHandlingQueue, dequeueDelay).ConfigureAwait(false);
// Assert
Assert.AreEqual(appPath, pathFromQueue);
Assert.AreEqual(0, eventHandlingQueue.Count);
}
[DataTestMethod]
[DataRow(5)]
public async Task EventHandlerMustReturnPathAndRetainDifferentFilePathsInQueueAsync(int itemCount)
{
// Arrange
int dequeueDelay = 0;
string firstAppPath = "appPath1";
string secondAppPath = "appPath2";
ConcurrentQueue<string> eventHandlingQueue = new ConcurrentQueue<string>();
for (int i = 0; i < itemCount; i++)
{
eventHandlingQueue.Enqueue(firstAppPath);
}
for (int i = 0; i < itemCount; i++)
{
eventHandlingQueue.Enqueue(secondAppPath);
}
// Act
string pathFromQueue = await EventHandler.GetAppPathFromQueueAsync(eventHandlingQueue, dequeueDelay).ConfigureAwait(false);
// Assert
Assert.AreEqual(firstAppPath, pathFromQueue);
Assert.AreEqual(itemCount, eventHandlingQueue.Count);
}
[DataTestMethod]
[DataRow(5)]
public async Task EventHandlerMustReturnPathAndRetainAllPathsAfterEncounteringADifferentPathAsync(int itemCount)
{
// Arrange
int dequeueDelay = 0;
string firstAppPath = "appPath1";
string secondAppPath = "appPath2";
ConcurrentQueue<string> eventHandlingQueue = new ConcurrentQueue<string>();
for (int i = 0; i < itemCount; i++)
{
eventHandlingQueue.Enqueue(firstAppPath);
}
for (int i = 0; i < itemCount; i++)
{
eventHandlingQueue.Enqueue(secondAppPath);
}
for (int i = 0; i < itemCount; i++)
{
eventHandlingQueue.Enqueue(firstAppPath);
}
// Act
string pathFromQueue = await EventHandler.GetAppPathFromQueueAsync(eventHandlingQueue, dequeueDelay).ConfigureAwait(false);
// Assert
Assert.AreEqual(firstAppPath, pathFromQueue);
Assert.AreEqual(itemCount * 2, eventHandlingQueue.Count);
}
}
}
@@ -0,0 +1,137 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wox.Infrastructure.Storage;
namespace Microsoft.Plugin.Program.UnitTests.Storage
{
[TestClass]
public class ListRepositoryTests
{
[TestMethod]
public void ContainsShouldReturnTrueWhenListIsInitializedWithItem()
{
// Arrange
var itemName = "originalItem1";
ListRepository<string> repository = new ListRepository<string>() { itemName };
// Act
var result = repository.Contains(itemName);
// Assert
Assert.IsTrue(result);
}
[TestMethod]
public void ContainsShouldReturnTrueWhenListIsUpdatedWithAdd()
{
// Arrange
ListRepository<string> repository = new ListRepository<string>();
// Act
var itemName = "newItem";
repository.Add(itemName);
var result = repository.Contains(itemName);
// Assert
Assert.IsTrue(result);
}
[TestMethod]
public void ContainsShouldReturnFalseWhenListIsUpdatedWithRemove()
{
// Arrange
var itemName = "originalItem1";
ListRepository<string> repository = new ListRepository<string>() { itemName };
// Act
repository.Remove(itemName);
var result = repository.Contains(itemName);
// Assert
Assert.IsFalse(result);
}
[TestMethod]
public async Task AddShouldNotThrowWhenBeingIterated()
{
// Arrange
ListRepository<string> repository = new ListRepository<string>();
var numItems = 1000;
for (var i = 0; i < numItems; ++i)
{
repository.Add($"OriginalItem_{i}");
}
// Act - Begin iterating on one thread
var iterationTask = Task.Run(() =>
{
var remainingIterations = 10000;
while (remainingIterations > 0)
{
foreach (var item in repository)
{
// keep iterating
}
--remainingIterations;
}
});
// Act - Insert on another thread
var addTask = Task.Run(() =>
{
for (var i = 0; i < numItems; ++i)
{
repository.Add($"NewItem_{i}");
}
});
// Assert that this does not throw. Collections that aren't synchronized will throw an invalidoperatioexception if the list is modified while enumerating
await Task.WhenAll(new Task[] { iterationTask, addTask }).ConfigureAwait(false);
}
[TestMethod]
public async Task RemoveShouldNotThrowWhenBeingIterated()
{
// Arrange
ListRepository<string> repository = new ListRepository<string>();
var numItems = 1000;
for (var i = 0; i < numItems; ++i)
{
repository.Add($"OriginalItem_{i}");
}
// Act - Begin iterating on one thread
var iterationTask = Task.Run(() =>
{
var remainingIterations = 10000;
while (remainingIterations > 0)
{
foreach (var item in repository)
{
// keep iterating
}
--remainingIterations;
}
});
// Act - Remove on another thread
var addTask = Task.Run(() =>
{
for (var i = 0; i < numItems; ++i)
{
repository.Remove($"OriginalItem_{i}");
}
});
// Assert that this does not throw. Collections that aren't synchronized will throw an invalidoperatioexception if the list is modified while enumerating
await Task.WhenAll(new Task[] { iterationTask, addTask }).ConfigureAwait(false);
}
}
}
@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.Plugin.Program.UnitTests.Storage
{
public class PackageRepositoryTest
{
}
}
@@ -0,0 +1,392 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Plugin.Program.Storage;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Wox.Infrastructure;
using Wox.Infrastructure.FileSystemHelper;
using Wox.Infrastructure.Storage;
using Win32Program = Microsoft.Plugin.Program.Programs.Win32Program;
namespace Microsoft.Plugin.Program.UnitTests.Storage
{
[TestClass]
public class Win32ProgramRepositoryTest
{
private readonly ProgramPluginSettings _settings = new ProgramPluginSettings();
private readonly string[] _pathsToWatch = new string[] { "location1", "location2" };
private List<IFileSystemWatcherWrapper> _fileSystemWatchers;
private List<Mock<IFileSystemWatcherWrapper>> _fileSystemMocks;
private static readonly string[] Path = new string[] { "URL=steam://rungameid/1258080", "IconFile=iconFile" };
[TestInitialize]
public void SetFileSystemWatchers()
{
_fileSystemWatchers = new List<IFileSystemWatcherWrapper>();
_fileSystemMocks = new List<Mock<IFileSystemWatcherWrapper>>();
for (int index = 0; index < _pathsToWatch.Length; index++)
{
var mockFileWatcher = new Mock<IFileSystemWatcherWrapper>();
_fileSystemMocks.Add(mockFileWatcher);
_fileSystemWatchers.Add(mockFileWatcher.Object);
}
}
[DataTestMethod]
[DataRow("Name", "ExecutableName", "FullPath", "description1", "description2")]
public void Win32RepositoryMustNotStoreDuplicatesWhileAddingItemsWithSameHashCode(string name, string exename, string fullPath, string description1, string description2)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
Win32Program item1 = new Win32Program
{
Name = name,
ExecutableName = exename,
FullPath = fullPath,
Description = description1,
};
Win32Program item2 = new Win32Program
{
Name = name,
ExecutableName = exename,
FullPath = fullPath,
Description = description2,
};
// Act
win32ProgramRepository.Add(item1);
Assert.AreEqual(1, win32ProgramRepository.Count());
// To add an item with the same hashCode, ie, same name, exename and fullPath
win32ProgramRepository.Add(item2);
// Assert, count still remains 1 because they are duplicate items
Assert.AreEqual(1, win32ProgramRepository.Count());
}
[DataTestMethod]
[DataRow("path.appref-ms")]
public void Win32ProgramRepositoryMustCallOnAppCreatedForApprefAppsWhenCreatedEventIsRaised(string path)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Created, "directory", path);
// Act
_fileSystemMocks[0].Raise(m => m.Created += null, e);
// Assert
Assert.AreEqual(1, win32ProgramRepository.Count());
Assert.AreEqual(Win32Program.ApplicationType.ApprefApplication, win32ProgramRepository.ElementAt(0).AppType);
}
[DataTestMethod]
[DataRow("directory", "path.appref-ms")]
public void Win32ProgramRepositoryMustCallOnAppDeletedForApprefAppsWhenDeletedEventIsRaised(string directory, string path)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Deleted, directory, path);
string fullPath = directory + "\\" + path;
Win32Program item = Win32Program.GetAppFromPath(fullPath);
win32ProgramRepository.Add(item);
// Act
_fileSystemMocks[0].Raise(m => m.Deleted += null, e);
// Assert
Assert.AreEqual(0, win32ProgramRepository.Count());
}
[DataTestMethod]
[DataRow("directory", "oldpath.appref-ms", "newpath.appref-ms")]
public async Task Win32ProgramRepositoryMustCallOnAppRenamedForApprefAppsWhenRenamedEventIsRaised(string directory, string oldpath, string newpath)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, newpath, oldpath);
string oldFullPath = directory + "\\" + oldpath;
string newFullPath = directory + "\\" + newpath;
Win32Program olditem = Win32Program.GetAppFromPath(oldFullPath);
Win32Program newitem = Win32Program.GetAppFromPath(newFullPath);
win32ProgramRepository.Add(olditem);
// Act
_fileSystemMocks[0].Raise(m => m.Renamed += null, e);
// We need to wait more than one second to make sure our test can pass
await Task.Delay(2 * Win32ProgramRepository.OnRenamedEventWaitTime).ConfigureAwait(false);
// Assert
Assert.AreEqual(1, win32ProgramRepository.Count());
Assert.IsTrue(win32ProgramRepository.Contains(newitem));
Assert.IsFalse(win32ProgramRepository.Contains(olditem));
}
[DataTestMethod]
[DataRow("path.exe")]
public void Win32ProgramRepositoryMustCallOnAppCreatedForExeAppsWhenCreatedEventIsRaised(string path)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Created, "directory", path);
// FileVersionInfo must be mocked for exe applications
var mockFileVersionInfo = new Mock<IFileVersionInfoWrapper>();
mockFileVersionInfo.Setup(m => m.GetVersionInfo(It.IsAny<string>())).Returns((FileVersionInfo)null);
Win32Program.FileVersionInfoWrapper = mockFileVersionInfo.Object;
// Act
_fileSystemMocks[0].Raise(m => m.Created += null, e);
// Assert
Assert.AreEqual(1, win32ProgramRepository.Count());
Assert.AreEqual(Win32Program.ApplicationType.Win32Application, win32ProgramRepository.ElementAt(0).AppType);
}
[DataTestMethod]
[DataRow("directory", "path.exe")]
public void Win32ProgramRepositoryMustCallOnAppDeletedForExeAppsWhenDeletedEventIsRaised(string directory, string path)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Deleted, directory, path);
// FileVersionInfo must be mocked for exe applications
var mockFileVersionInfo = new Mock<IFileVersionInfoWrapper>();
mockFileVersionInfo.Setup(m => m.GetVersionInfo(It.IsAny<string>())).Returns((FileVersionInfo)null);
Win32Program.FileVersionInfoWrapper = mockFileVersionInfo.Object;
string fullPath = directory + "\\" + path;
Win32Program item = Win32Program.GetAppFromPath(fullPath);
win32ProgramRepository.Add(item);
// Act
_fileSystemMocks[0].Raise(m => m.Deleted += null, e);
// Assert
Assert.AreEqual(0, win32ProgramRepository.Count());
}
[DataTestMethod]
[DataRow("directory", "oldpath.appref-ms", "newpath.appref-ms")]
public async Task Win32ProgramRepositoryMustCallOnAppRenamedForExeAppsWhenRenamedEventIsRaised(string directory, string oldpath, string newpath)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, newpath, oldpath);
string oldFullPath = directory + "\\" + oldpath;
string newFullPath = directory + "\\" + newpath;
// FileVersionInfo must be mocked for exe applications
var mockFileVersionInfo = new Mock<IFileVersionInfoWrapper>();
mockFileVersionInfo.Setup(m => m.GetVersionInfo(It.IsAny<string>())).Returns((FileVersionInfo)null);
Win32Program.FileVersionInfoWrapper = mockFileVersionInfo.Object;
Win32Program olditem = Win32Program.GetAppFromPath(oldFullPath);
Win32Program newitem = Win32Program.GetAppFromPath(newFullPath);
win32ProgramRepository.Add(olditem);
// Act
_fileSystemMocks[0].Raise(m => m.Renamed += null, e);
// We need to wait more than one second to make sure our test can pass
await Task.Delay(2 * Win32ProgramRepository.OnRenamedEventWaitTime).ConfigureAwait(false);
// Assert
Assert.AreEqual(1, win32ProgramRepository.Count());
Assert.IsTrue(win32ProgramRepository.Contains(newitem));
Assert.IsFalse(win32ProgramRepository.Contains(olditem));
}
[DataTestMethod]
[DataRow("path.url")]
public void Win32ProgramRepositoryMustNotCreateUrlAppWhenCreatedEventIsRaised(string path)
{
// We are handing internet shortcut apps using the Changed event instead
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Created, "directory", path);
// File.ReadAllLines must be mocked for url applications
var mockFile = new Mock<IFile>();
mockFile.Setup(m => m.ReadAllLines(It.IsAny<string>())).Returns(Path);
Win32Program.FileWrapper = mockFile.Object;
// Act
_fileSystemMocks[0].Raise(m => m.Created += null, e);
// Assert
Assert.AreEqual(0, win32ProgramRepository.Count());
}
[DataTestMethod]
[DataRow("path.exe")]
[DataRow("path.lnk")]
[DataRow("path.appref-ms")]
public void Win32ProgramRepositoryMustNotCreateAnyAppOtherThanUrlAppWhenChangedEventIsRaised(string path)
{
// We are handing internet shortcut apps using the Changed event instead
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Changed, "directory", path);
// FileVersionInfo must be mocked for exe applications
var mockFileVersionInfo = new Mock<IFileVersionInfoWrapper>();
mockFileVersionInfo.Setup(m => m.GetVersionInfo(It.IsAny<string>())).Returns((FileVersionInfo)null);
Win32Program.FileVersionInfoWrapper = mockFileVersionInfo.Object;
// ShellLinkHelper must be mocked for lnk applications
var mockShellLink = new Mock<IShellLinkHelper>();
mockShellLink.Setup(m => m.RetrieveTargetPath(It.IsAny<string>())).Returns(string.Empty);
Win32Program.ShellLinkHelper = mockShellLink.Object;
// Act
_fileSystemMocks[0].Raise(m => m.Changed += null, e);
// Assert
Assert.AreEqual(0, win32ProgramRepository.Count());
}
[DataTestMethod]
[DataRow("directory", "path.url")]
public void Win32ProgramRepositoryMustCallOnAppDeletedForUrlAppsWhenDeletedEventIsRaised(string directory, string path)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Deleted, directory, path);
// File.ReadAllLines must be mocked for url applications
var mockFile = new Mock<IFile>();
mockFile.Setup(m => m.ReadLines(It.IsAny<string>())).Returns(Path);
Win32Program.FileWrapper = mockFile.Object;
string fullPath = directory + "\\" + path;
Win32Program item = Win32Program.GetAppFromPath(fullPath);
win32ProgramRepository.Add(item);
// Act
_fileSystemMocks[0].Raise(m => m.Deleted += null, e);
// Assert
Assert.AreEqual(0, win32ProgramRepository.Count());
}
[DataTestMethod]
[DataRow("directory", "oldpath.url", "newpath.url")]
public async Task Win32ProgramRepositoryMustCallOnAppRenamedForUrlAppsWhenRenamedEventIsRaised(string directory, string oldpath, string newpath)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, newpath, oldpath);
// File.ReadAllLines must be mocked for url applications
var mockFile = new Mock<IFile>();
mockFile.Setup(m => m.ReadLines(It.IsAny<string>())).Returns(Path);
Win32Program.FileWrapper = mockFile.Object;
string oldFullPath = directory + "\\" + oldpath;
string newFullPath = directory + "\\" + newpath;
Win32Program olditem = Win32Program.GetAppFromPath(oldFullPath);
Win32Program newitem = Win32Program.GetAppFromPath(newFullPath);
win32ProgramRepository.Add(olditem);
// Act
_fileSystemMocks[0].Raise(m => m.Renamed += null, e);
// We need to wait more than one second to make sure our test can pass
await Task.Delay(2 * Win32ProgramRepository.OnRenamedEventWaitTime).ConfigureAwait(false);
// Assert
Assert.AreEqual(1, win32ProgramRepository.Count());
Assert.IsTrue(win32ProgramRepository.Contains(newitem));
Assert.IsFalse(win32ProgramRepository.Contains(olditem));
}
[DataTestMethod]
[DataRow("directory", "path.lnk")]
public void Win32ProgramRepositoryMustCallOnAppDeletedForLnkAppsWhenDeletedEventIsRaised(string directory, string path)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
FileSystemEventArgs e = new FileSystemEventArgs(WatcherChangeTypes.Deleted, directory, path);
// ShellLinkHelper must be mocked for lnk applications
var mockShellLink = new Mock<IShellLinkHelper>();
mockShellLink.Setup(m => m.RetrieveTargetPath(It.IsAny<string>())).Returns(string.Empty);
Win32Program.ShellLinkHelper = mockShellLink.Object;
string fullPath = directory + "\\" + path;
Win32Program item = new Win32Program
{
Name = "path",
ExecutableName = "path.exe",
ParentDirectory = "directory",
FullPath = "directory\\path.exe",
LnkFilePath = "directory\\path.lnk", // This must be equal for lnk applications
};
win32ProgramRepository.Add(item);
// Act
_fileSystemMocks[0].Raise(m => m.Deleted += null, e);
// Assert
Assert.AreEqual(0, win32ProgramRepository.Count());
}
[DataTestMethod]
[DataRow("directory", "oldpath.lnk", "path.lnk")]
public async Task Win32ProgramRepositoryMustCallOnAppRenamedForLnkAppsWhenRenamedEventIsRaised(string directory, string oldpath, string path)
{
// Arrange
Win32ProgramRepository win32ProgramRepository = new Win32ProgramRepository(_fileSystemWatchers, _settings, _pathsToWatch);
RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, path, oldpath);
string oldFullPath = directory + "\\" + oldpath;
string newFullPath = directory + "\\" + path;
string linkingTo = Directory.GetCurrentDirectory();
// ShellLinkHelper must be mocked for lnk applications
var mockShellLink = new Mock<IShellLinkHelper>();
mockShellLink.Setup(m => m.RetrieveTargetPath(It.IsAny<string>())).Returns(linkingTo);
Win32Program.ShellLinkHelper = mockShellLink.Object;
// old item and new item are the actual items when they are in existence
Win32Program olditem = Win32Program.GetAppFromPath(oldFullPath);
Win32Program newitem = Win32Program.GetAppFromPath(newFullPath);
win32ProgramRepository.Add(olditem);
// Act
_fileSystemMocks[0].Raise(m => m.Renamed += null, e);
// We need to wait more than one second to make sure our test can pass
await Task.Delay(2 * Win32ProgramRepository.OnRenamedEventWaitTime).ConfigureAwait(false);
// Assert
Assert.AreEqual(1, win32ProgramRepository.Count());
Assert.IsTrue(win32ProgramRepository.Contains(newitem));
Assert.IsFalse(win32ProgramRepository.Contains(olditem));
}
}
}