Merge pull request #3367 from keymanapp/fix/windows/setup-cleanup-3339

feat(windows): strip ' (1)' from filename in setup
This commit is contained in:
Marc Durdin 2020-07-20 12:23:31 +10:00 • committed by GitHub
commit c813e47622
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1530 additions and 33 deletions

View file

@ -117,6 +117,7 @@ type
FIsNewerAvailable: Boolean;
FTempPath: string;
FShouldInstallKeyman: Boolean;
FTier: string;
function GetBestMsi: TInstallInfoFileLocation;
function GetPackageMetadata(const KmpFilename: string; p: TPackage): Boolean;
public
@ -124,7 +125,7 @@ type
destructor Destroy; override;
procedure LoadSetupInf(const SetupInfPath: string);
procedure LocatePackagesFromFilename(const Filename: string);
procedure LocatePackagesAndTierFromFilename(Filename: string);
procedure LocatePackagesFromParameter(const Param: string);
procedure LocatePackagesInPath(const path: string);
@ -152,6 +153,8 @@ type
property StartDisabled: Boolean read FStartDisabled;
property StartWithConfiguration: Boolean read FStartWithConfiguration;
property Tier: string read FTier write FTier;
property ShouldInstallKeyman: Boolean read FShouldInstallKeyman write FShouldInstallKeyman;
end;
@ -181,6 +184,7 @@ begin
FMsiLocations := TInstallInfoFileLocations.Create;
FPackages := TInstallInfoPackages.Create;
FStrings := TStringList.Create;
FTier := KeymanVersion.CKeymanVersionInfo.Tier;
FShouldInstallKeyman := True;
end;
@ -328,17 +332,38 @@ begin
end;
end;
procedure TInstallInfo.LocatePackagesFromFilename(const Filename: string);
procedure TInstallInfo.LocatePackagesAndTierFromFilename(Filename: string);
const
SKeymanSetupPrefix = 'keyman-setup';
SKeymanSetup_Alpha = SKeymanSetupPrefix+'-'+TIER_ALPHA;
SKeymanSetup_Beta = SKeymanSetupPrefix+'-'+TIER_BETA;
SKeymanSetup_Stable = SKeymanSetupPrefix+'-'+TIER_STABLE;
var
n: Integer;
res: TArray<string>;
id, FBCP47: string;
p, id, FBCP47: string;
m: TMatch;
begin
res := TRegEx.Split(ExtractFileName(ChangeFileExt(Filename, '')), '\.');
if (Length(res) < 2) or (res[0].ToLower <> 'keyman-setup') then
// No packages embedded in filename
// Get just the base filename
Filename := ExtractFileName(ChangeFileExt(Filename, ''));
// Strip " (1)" appended for multiple downloads of same file by most browsers
m := TRegEx.Match(Filename, '^('+SKeymanSetupPrefix+'.+) \(\d+\)$');
if m.Success then
Filename := m.Groups[1].Value;
// Look for our recognised pattern of keyman-setup.package_id.bcp47...
res := TRegEx.Split(Filename, '\.');
if (Length(res) < 1) or not res[0].ToLower.StartsWith(SKeymanSetupPrefix) then
// No packages embedded in filename, or not a recognised filename pattern
Exit;
// Look for an embedded tier in the filename, if not set, use default
p := res[0].ToLower;
if p.Equals(SKeymanSetup_Stable) then FTier := TIER_STABLE
else if p.Equals(SKeymanSetup_Beta) then FTier := TIER_BETA
else if p.Equals(SKeymanSetup_Alpha) then FTier := TIER_ALPHA;
n := 1;
while n < Length(res) do
begin

View file

@ -46,7 +46,7 @@ begin
try
http.Request.SetURL(MakeAPIURL(API_Path_UpdateCheck_Windows));
http.Fields.Add('version', AnsiString(currentVersion));
http.Fields.Add('tier', AnsiString(KeymanVersion.CKeymanVersionInfo.Tier));
http.Fields.Add('tier', AnsiString(AInstallInfo.Tier));
http.Fields.Add('update', '0'); // This is probably a fresh install of a package, not an update
for pack in AInstallInfo.Packages do
http.Fields.Add(AnsiString('package_'+pack.ID), AnsiString(pack.Locations.LatestVersion));

View file

@ -87,7 +87,9 @@ type
{ Download dialog }
ssDownloadingTitle,
ssDownloadingText
ssDownloadingText,
ssOffline
);
const
@ -157,7 +159,11 @@ const
{ssOptionsDefaultLanguage} 'Default language',
{ssDownloadingTitle} 'Downloading %0:s', // %0:s: filename
{ssDownloadingText} 'Downloading %0:s' // %0:s: filename
{ssDownloadingText} 'Downloading %0:s', // %0:s: filename
{ssOffline} 'Keyman Setup could not connect to keyman.com to download additional resources.'#13#10#13#10+
'Please check that you are online, and give Keyman Setup permission to access the Internet in your firewall settings.'#13#10#13#10+
'Click Abort to exit Setup, Retry to try and download resources again, or Ignore to continue offline.'
);

View file

@ -91,13 +91,19 @@ begin
IDCANCEL: Result := mrCancel;
IDYES: Result := mrYes;
IDNO: Result := mrNo;
IDABORT: Result := mrAbort;
IDIGNORE: Result := mrIgnore;
IDRETRY: Result := mrRetry;
else Result := mrOk;
end;
end;
procedure ShowMessageW(const Message: WideString);
begin
Tnt_MessageBoxW(GetActiveWindow, PWideChar(Message), PChar(FInstallInfo.Text(ssMessageBoxTitle)), MB_OK);
if Assigned(FInstallInfo) then
Tnt_MessageBoxW(GetActiveWindow, PWideChar(Message), PChar(FInstallInfo.Text(ssMessageBoxTitle)), MB_OK)
else
Tnt_MessageBoxW(GetActiveWindow, PWideChar(Message), PChar('Setup'), MB_OK);
end;
end.

View file

@ -14,6 +14,7 @@ object frmHTML: TfrmHTML
KeyPreview = True
OldCreateOrder = False
Position = poScreenCenter
OnDestroy = FormDestroy
DesignSize = (
666
313)

View file

@ -51,13 +51,18 @@ type
procedure cmdForwardClick(Sender: TObject);
procedure webCommandStateChange(ASender: TObject; Command: Integer;
Enable: WordBool);
procedure FormDestroy(Sender: TObject);
private
FFilename: string;
public
procedure ShowFile(const FileName: WideString);
procedure ShowText(const Text: string);
end;
implementation
uses
utildir,
utilexecute;
{$R *.DFM}
@ -70,6 +75,20 @@ begin
web.Navigate(FileName);
end;
procedure TfrmHTML.ShowText(const Text: string);
var
stream: TStringStream;
begin
FFilename := KGetTempFileName('.txt');
stream := TStringStream.Create(Text, TEncoding.UTF8);
try
stream.SaveToFile(FFilename);
finally
stream.Free;
end;
ShowFile(FFileName);
end;
procedure TfrmHTML.webCommandStateChange(ASender: TObject; Command: Integer;
Enable: WordBool);
begin
@ -102,5 +121,11 @@ begin
web.ExecWB(OLECMDID_PRINT, 0);
end;
procedure TfrmHTML.FormDestroy(Sender: TObject);
begin
if FFileName <> '' then
System.SysUtils.DeleteFile(FFileName);
end;
end.

View file

@ -102,6 +102,8 @@ uses
{ TfrmInstallOptions }
procedure TfrmInstallOptions.FormCreate(Sender: TObject);
var
FAllowOptions: Boolean;
begin
Caption := FInstallInfo.Text(ssOptionsTitle);
chkStartWithWindows.Caption := FInstallInfo.Text(ssOptionsStartWithWindows);
@ -117,6 +119,12 @@ begin
lblSelectModulesToInstall.Caption := FInstallInfo.Text(ssOptionsTitleSelectModulesToInstall);
lblAssociatedKeyboardLanguage.Caption := FInstallInfo.Text(ssOptionsTitleAssociatedKeyboardLanguage);
FAllowOptions := not FInstallInfo.IsInstalled and FInstallInfo.IsNewerAvailable;
lblDefaultKeymanSettings.Visible := FAllowOptions;
chkAutomaticallyReportUsage.Visible := FAllowOptions;
chkCheckForUpdates.Visible := FAllowOptions;
chkStartWithWindows.Visible := FAllowOptions;
SetupDynamicOptions;
end;
@ -241,8 +249,8 @@ begin
end
else
case FInstallInfo.BestMsi.LocationType of
iilLocal: Text := FInstallInfo.Text(ssOptionsInstallKeyman, [FInstallInfo.BestMsi.Version]);
iilOnline: Text := FInstallInfo.Text(ssOptionsDownloadInstallKeyman, [FInstallInfo.BestMsi.Version, FormatFileSize(FInstallInfo.BestMsi.Size)]);
iilLocal: Text := FInstallInfo.Text(ssOptionsUpgradeKeyman, [FInstallInfo.BestMsi.Version]);
iilOnline: Text := FInstallInfo.Text(ssOptionsDownloadUpgradeKeyman, [FInstallInfo.BestMsi.Version, FormatFileSize(FInstallInfo.BestMsi.Size)]);
end;
end
else if FInstallInfo.IsInstalled then

View file

@ -137,6 +137,7 @@ uses
OnlineConstants,
SFX,
SetupStrings,
Keyman.System.MITLicense,
Keyman.System.UpgradeRegistryKeys,
KeymanVersion,
RegistryHelpers,
@ -643,9 +644,7 @@ procedure TfrmRunDesktop.lblLicenseClick(Sender: TObject);
begin
with TfrmHTML.Create(Self) do // I2606
try
Assert(FALSE, 'TODO: show linked in license content');
// TODO:
// ShowFile(FInstallInfo.LicenseFileName); // I3476
ShowText(SKeymanMITLicense);
ShowModal;
finally
Free;
@ -976,6 +975,7 @@ begin
end;
lblStatus.Caption := Text;
lblStatus.Update;
Update;
end;

View file

@ -92,10 +92,11 @@ procedure InstallKeyboardsInOldVersion(const ShellPath: string); forward;
procedure DoExtractOnly(FSilent: Boolean; const FExtractOnly_Path: string); forward;
function CreateTempDir: string; forward;
procedure RemoveTempDir(const path: string); forward;
procedure ProcessCommandLine(var FPromptForReboot, FSilent, FForceOffline, FExtractOnly, FContinueSetup, FStartAfterInstall, FDisableUpgradeFrom6Or7Or8: Boolean; var FPackages, FExtractPath: string); forward;
procedure ProcessCommandLine(var FPromptForReboot, FSilent, FForceOffline, FExtractOnly, FContinueSetup, FStartAfterInstall, FDisableUpgradeFrom6Or7Or8: Boolean; var FPackages, FExtractPath, FTier: string); forward;
procedure SetExitVal(c: Integer); forward;
function IsKeymanDesktop7Installed: string; forward;
function IsKeymanDesktop8Installed: string; forward;
function GetResourcesFromOnline(FSilent: Boolean; var FForceOffline: Boolean): Boolean; forward;
var
FNiceExitCodes: Boolean = True; // always, now
@ -116,23 +117,21 @@ var
FPromptForReboot: Boolean; // I3355 // I3500
FSilent: Boolean;
FForceOffline: Boolean;
FPackages, FExtractOnly_Path: string;
FTier, FPackages, FExtractOnly_Path: string;
BEGIN
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
try
try
Vcl.Forms.Application.Icon.LoadFromResourceID(hInstance, 1); // I2611
InitCommonControl(ICC_PROGRESS_CLASS);
FTempPath := CreateTempDir;
try
FTempPath := CreateTempDir;
FInstallInfo := TInstallInfo.Create(FTempPath);
try
InitCommonControl(ICC_PROGRESS_CLASS);
FInstallInfo := TInstallInfo.Create(FTempPath);
{ Display the dialog }
ProcessCommandLine(FPromptForReboot, FSilent, FForceOffline, FExtractOnly, FContinueSetup, FStartAfterInstall, FDisableUpgradeFrom6Or7Or8, FPackages, FExtractOnly_Path); // I2738, I2847 // I3355 // I3500 // I4293
ProcessCommandLine(FPromptForReboot, FSilent, FForceOffline, FExtractOnly, FContinueSetup, FStartAfterInstall, FDisableUpgradeFrom6Or7Or8, FPackages, FExtractOnly_Path, FTier); // I2738, I2847 // I3355 // I3500 // I4293
GetRunTools.Silent := FSilent;
if FExtractOnly then
@ -162,7 +161,7 @@ BEGIN
// it to download khmer_angkor from the Keyman cloud and install it
// for bcp47 tag km. See the setup documentation for more
// examples.
FInstallInfo.LocatePackagesFromFilename(ParamStr(0));
FInstallInfo.LocatePackagesAndTierFromFilename(ParamStr(0));
// Additionally, packages can be specified on the command line, with
// the -p parameter, e.g. -p khmer_angkor=km,sil_euro_latin=fr
@ -176,11 +175,16 @@ BEGIN
// this executable
FInstallInfo.LocatePackagesInPath(ProgramPath);
GetRunTools.CheckInternetConnectedState;
// Lookup a tier from command line parameter
if FTier <> '' then
FInstallInfo.Tier := FTier;
if not FForceOffline and GetRunTools.Online then
// TODO: retry strategies (and prompt around firewall etc)
TOnlineResourceCheck.QueryServer(FSilent, FInstallInfo);
// Try and get information from online
if not GetResourcesFromOnline(FSilent, FForceOffline) then
begin
SetExitVal(ERROR_FILE_NOT_FOUND);
Exit;
end;
// This loads setup.inf, if present, for various additional strings and settings
// The bundled installer usually contains a setup.inf.
@ -226,13 +230,13 @@ BEGIN
Free;
end;
finally
RemoveTempDir(FTempPath);
FreeAndNil(FInstallInfo);
end;
SetExitVal(ERROR_SUCCESS);
finally
FInstallInfo.Free;
RemoveTempDir(FTempPath);
end;
except
on e:Exception do
@ -250,6 +254,43 @@ BEGIN
end;
end;
function GetResourcesFromOnline(FSilent: Boolean; var FForceOffline: Boolean): Boolean;
begin
if FForceOffline then
Exit(True);
repeat
try
GetRunTools.CheckInternetConnectedState;
if GetRunTools.Online then
TOnlineResourceCheck.QueryServer(FSilent, FInstallInfo);
// We've succeeded.
Exit(True);
except
on E:Exception do
begin
GetRunTools.LogInfo('Could not connect to site: '+E.Message);
if FSilent then
begin
// We log and attempt to continue
FForceOffline := True;
end
else
begin
case MessageDlgW(FInstallInfo.Text(ssOffline), mtError, mbAbortRetryIgnore, 0) of
mrAbort: Exit(False);
mrRetry: Continue;
mrIgnore: FForceOffline := True;
end;
end;
end;
end;
until FForceOffline;
Result := True;
end;
function CheckForOldVersionScenario: Boolean; // I4460
var
OldKMShellPath: string;
@ -381,7 +422,7 @@ begin
DeletePath(ExcludeTrailingPathDelimiter(path)); // I3476
end;
procedure ProcessCommandLine(var FPromptForReboot, FSilent, FForceOffline, FExtractOnly, FContinueSetup, FStartAfterInstall, FDisableUpgradeFrom6Or7Or8: Boolean; var FPackages, FExtractPath: string); // I2847 // I3355 // I3500 // I4293
procedure ProcessCommandLine(var FPromptForReboot, FSilent, FForceOffline, FExtractOnly, FContinueSetup, FStartAfterInstall, FDisableUpgradeFrom6Or7Or8: Boolean; var FPackages, FExtractPath, FTier: string); // I2847 // I3355 // I3500 // I4293
var
i: Integer;
begin
@ -428,6 +469,15 @@ begin
// e.g. -p khmer_angkor=km,sil_euro_latin=fr
Inc(i);
FPackages := ParamStr(i);
end
else if SameText(ParamStr(i), '-t') then
begin
Inc(i);
FTier := ParamStr(i).ToLower.Trim;
if not FTier.Equals(TIER_ALPHA) and not FTier.Equals(TIER_BETA) and not FTier.Equals(TIER_STABLE) then
begin
FTier := '';
end;
end;
Inc(i);
end;

View file

@ -43,7 +43,8 @@ uses
kmpinffile in '..\..\global\delphi\general\kmpinffile.pas',
PackageFileFormats in '..\..\global\delphi\general\PackageFileFormats.pas',
Keyman.Setup.System.ResourceDownloader in 'Keyman.Setup.System.ResourceDownloader.pas',
httpuploader in '..\..\global\delphi\general\httpuploader.pas';
httpuploader in '..\..\global\delphi\general\httpuploader.pas',
Keyman.System.MITLicense in '..\..\global\delphi\general\Keyman.System.MITLicense.pas';
{$R icons.res}
{$R version.res}

View file

@ -143,6 +143,7 @@
<DCCReference Include="..\..\global\delphi\general\PackageFileFormats.pas"/>
<DCCReference Include="Keyman.Setup.System.ResourceDownloader.pas"/>
<DCCReference Include="..\..\global\delphi\general\httpuploader.pas"/>
<DCCReference Include="..\..\global\delphi\general\Keyman.System.MITLicense.pas"/>
<BuildConfiguration Include="Debug">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>

View file

@ -0,0 +1,31 @@
unit Keyman.System.MITLicense;
interface
const
SKeymanMITLicense =
'The MIT License'#13#10+
#13#10+
'Copyright (c) 2017-2020 SIL International'#13#10+
#13#10+
'Permission is hereby granted, free of charge, to any person obtaining a copy'#13#10+
'of this software and associated documentation files (the "Software"), to deal'#13#10+
'in the Software without restriction, including without limitation the rights'#13#10+
'to use, copy, modify, merge, publish, distribute, sublicense, and/or sell'#13#10+
'copies of the Software, and to permit persons to whom the Software is'#13#10+
'furnished to do so, subject to the following conditions:'#13#10+
#13#10+
'The above copyright notice and this permission notice shall be included in all'#13#10+
'copies or substantial portions of the Software.'#13#10+
#13#10+
'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR'#13#10+
'IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,'#13#10+
'FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE'#13#10+
'AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER'#13#10+
'LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,'#13#10+
'OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE'#13#10+
'SOFTWARE.'#13#10;
implementation
end.

View file

@ -5,7 +5,7 @@
# ----------------------------------------------------------------------
TARGETS=keyboard-info keyboard-js-info keyboard-package-versions \
kmx-file-languages package-info new-tests jsonutil
kmx-file-languages package-info new-tests jsonutil windows-setup
test:
$(MAKE) -DTARGET=test $(TARGETS)
@ -38,6 +38,10 @@ jsonutil:
cd $(ROOT)\src\unit-tests\jsonutil
$(MAKE) $(TARGET)
windows-setup:
cd $(ROOT)\src\unit-tests\windows-setup
$(MAKE) $(TARGET)
new-tests:
cd $(ROOT)\src\test\unit-tests
$(MAKE) $(TARGET)

View file

@ -0,0 +1,190 @@
unit Keyman.System.Test.InstallInfoTest;
interface
uses
System.Classes,
System.SysUtils,
DUnitX.TestFramework;
type
[TestFixture]
TInstallInfoTest = class(TObject)
public
[Test]
procedure TestLocatePackagesAndTierFromFilename;
[Test]
procedure TestLocatePackagesFromParameter;
end;
implementation
uses
KeymanVersion,
Keyman.Setup.System.InstallInfo;
{ TInstallInfoTest }
procedure TInstallInfoTest.TestLocatePackagesAndTierFromFilename;
var
ii: TInstallInfo;
begin
ii := TInstallInfo.Create('');
try
// It should match a standard pattern
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup.khmer_angkor.km.exe');
Assert.AreEqual(CKeymanVersionInfo.Tier, ii.Tier);
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should match a standard pattern with a tier
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup-alpha.khmer_angkor.km.exe');
Assert.AreEqual(TIER_ALPHA, ii.Tier);
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should match a standard pattern with a tier
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup-beta.khmer_angkor.km.exe');
Assert.AreEqual(TIER_BETA, ii.Tier);
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should match a standard pattern with a tier
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup-stable.khmer_angkor.km.exe');
Assert.AreEqual(TIER_STABLE, ii.Tier);
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should match a standard pattern
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup.khmer_angkor.km.sil_euro_latin.fr.exe');
Assert.AreEqual(2, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
Assert.AreEqual('sil_euro_latin', ii.Packages[1].ID);
Assert.AreEqual('fr', ii.Packages[1].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should strip off " (1)" suffixes when these are added by web browser
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup.khmer_angkor.km (1).exe');
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should give an empty BCP 47 tag if one is not provided
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup.khmer_angkor.exe');
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.IsEmpty(ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should only match on keyman-setup
ii.LocatePackagesAndTierFromFilename('c:\foo\setup.khmer_angkor.km.exe');
Assert.AreEqual(0, ii.Packages.Count, 'setup.khmer_angkor.km.exe');
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should match packages with less common characters in filename
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup.khmer angkor.km.exe');
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should match packages with less common characters in filename
ii.LocatePackagesAndTierFromFilename('c:\foo\keyman-setup.khmer-angkor.km.exe');
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer-angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
end;
procedure TInstallInfoTest.TestLocatePackagesFromParameter;
var
ii: TInstallInfo;
begin
ii := TInstallInfo.Create('');
try
// It should match a standard pattern
ii.LocatePackagesFromParameter('khmer_angkor=km');
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should match a standard pattern
ii.LocatePackagesFromParameter('khmer_angkor=km,sil_euro_latin=fr');
Assert.AreEqual(2, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.AreEqual('km', ii.Packages[0].BCP47);
Assert.AreEqual('sil_euro_latin', ii.Packages[1].ID);
Assert.AreEqual('fr', ii.Packages[1].BCP47);
finally
ii.Free;
end;
ii := TInstallInfo.Create('');
try
// It should give an empty BCP 47 tag if one is not provided
ii.LocatePackagesFromParameter('khmer_angkor');
Assert.AreEqual(1, ii.Packages.Count);
Assert.AreEqual('khmer_angkor', ii.Packages[0].ID);
Assert.IsEmpty(ii.Packages[0].BCP47);
finally
ii.Free;
end;
end;
initialization
TDUnitX.RegisterTestFixture(TInstallInfoTest);
end.

View file

@ -0,0 +1,20 @@
#
# Test various components of Keyman for Windows Setup
#
# NOTE: The .dproj needs $(CI) added to the Delphi Compiler/Conditional defines (All
# configurations - all platforms) section in order for the CI flag to be passed in.
# (It's best to make this change in Delphi IDE).
#
!include ..\..\Defines.mak
test: build
-$(WIN32_TARGET_PATH)\WindowsSetupTest.exe -b -exit:continue
build:
$(DELPHI_MSBUILD) /p:CI=CI WindowsSetupTest.dproj
clean: def-clean
-rd /s/q Win32
!include ..\..\Target.mak

View file

@ -0,0 +1,79 @@
program WindowsSetupTest;
{$IFNDEF TESTINSIGHT}
{$APPTYPE CONSOLE}
{$ENDIF}{$STRONGLINKTYPES ON}
uses
System.SysUtils,
{$IFDEF TESTINSIGHT}
TestInsight.DUnitX,
{$ENDIF }
DUnitX.Loggers.Console,
DUnitX.Loggers.Xml.NUnit,
DUnitX.TestFramework,
Keyman.System.Test.InstallInfoTest in 'Keyman.System.Test.InstallInfoTest.pas',
Keyman.Setup.System.InstallInfo in '..\..\desktop\setup\Keyman.Setup.System.InstallInfo.pas',
PackageInfo in '..\..\global\delphi\general\PackageInfo.pas',
utilfiletypes in '..\..\global\delphi\general\utilfiletypes.pas',
StockFileNames in '..\..\global\delphi\cust\StockFileNames.pas',
utilstr in '..\..\global\delphi\general\utilstr.pas',
Unicode in '..\..\global\delphi\general\Unicode.pas',
JsonUtil in '..\..\global\delphi\general\JsonUtil.pas',
KeymanVersion in '..\..\global\delphi\general\KeymanVersion.pas',
utildir in '..\..\global\delphi\general\utildir.pas',
utilsystem in '..\..\global\delphi\general\utilsystem.pas',
RegistryKeys in '..\..\global\delphi\general\RegistryKeys.pas',
utilexecute in '..\..\global\delphi\general\utilexecute.pas',
GetOsVersion in '..\..\global\delphi\general\GetOsVersion.pas',
VersionInfo in '..\..\global\delphi\general\VersionInfo.pas',
SetupStrings in '..\..\desktop\setup\SetupStrings.pas',
kmpinffile in '..\..\global\delphi\general\kmpinffile.pas',
PackageFileFormats in '..\..\global\delphi\general\PackageFileFormats.pas';
var
runner : ITestRunner;
results : IRunResults;
logger : ITestLogger;
nunitLogger : ITestLogger;
begin
{$R *.res}
{$IFDEF TESTINSIGHT}
TestInsight.DUnitX.RunRegisteredTests;
exit;
{$ENDIF}
try
//Check command line options, will exit if invalid
TDUnitX.CheckCommandLine;
//Create the test runner
runner := TDUnitX.CreateRunner;
//Tell the runner to use RTTI to find Fixtures
runner.UseRTTI := True;
//tell the runner how we will log things
//Log to the console window
logger := TDUnitXConsoleLogger.Create(true);
runner.AddLogger(logger);
//Generate an NUnit compatible XML File
nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile);
runner.AddLogger(nunitLogger);
runner.FailsOnNoAsserts := False; //When true, Assertions must be made during tests;
//Run tests
results := runner.Execute;
if not results.AllPassed then
System.ExitCode := EXIT_ERRORS;
{$IFNDEF CI}
//We don't want this happening when running under CI.
if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then
begin
System.Write('Done.. press <Enter> key to quit.');
System.Readln;
end;
{$ENDIF}
except
on E: Exception do
System.Writeln(E.ClassName, ': ', E.Message);
end;
end.

File diff suppressed because it is too large Load diff