Skip to content

Commit

Permalink
Reinstall the MSIX before every test
Browse files Browse the repository at this point in the history
This way we ensure we carry no state from one test to the next one
  • Loading branch information
EduardGomezEscandell committed Nov 28, 2023
1 parent 9f20246 commit 939dbeb
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 36 deletions.
100 changes: 65 additions & 35 deletions end-to-end/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import (
var (
// testImagePath is the path to the test image.
testImagePath string

// msixPath is the path to the Ubuntu Pro For Windows MSIX.
msixPath string
)

const (
Expand Down Expand Up @@ -49,6 +52,9 @@ const (

// referenceDistro is the WSL distro that will be used to generate the test image.
referenceDistroAppx = "CanonicalGroupLimited.Ubuntu"

// up4wAppxPackage is the Ubuntu Pro For Windows package.
up4wAppxPackage = "CanonicalGroupLimited.UbuntuProForWindows"
)

func TestMain(m *testing.M) {
Expand Down Expand Up @@ -80,9 +86,8 @@ func TestMain(m *testing.M) {
log.Fatalf("Setup: %v\n", err)
}

if err := assertAppxInstalled(ctx, "CanonicalGroupLimited.UbuntuProForWindows"); err != nil {
log.Fatalf("Setup: %v\n", err)
}
log.Printf("MSIX package located at %s", msixPath)
log.Printf("Deb package located at %s", wslProServiceDebPath)

path, cleanup, err := generateTestImage(ctx, referenceDistro, wslProServiceDebPath)
if err != nil {
Expand All @@ -97,7 +102,7 @@ func TestMain(m *testing.M) {
log.Printf("Cleanup: registry: %v\n", err)
}

cmd := powershellf(ctx, "Get-AppxPackage -Name CanonicalGroupLimited.UbuntuProForWindows | Remove-AppxPackage")
cmd := powershellf(ctx, "Get-AppxPackage -Name %q | Remove-AppxPackage", up4wAppxPackage)
if out, err := cmd.CombinedOutput(); err != nil {
log.Printf("Cleanup: could not remove Appx: %v: %s", err, out)
}
Expand All @@ -106,24 +111,19 @@ func TestMain(m *testing.M) {
func usePrebuiltProject(ctx context.Context) (debPath string, err error) {
buildPath := os.Getenv(prebuiltPath)

// Remove Appx before installing
cmd := powershellf(ctx, "Get-AppxPackage CanonicalGroupLimited.UbuntuProForWindows | Remove-AppxPackage")
if out, err := cmd.CombinedOutput(); err != nil {
// (Probably because it was not installed)
log.Printf("Could not remove old AppxPackage: %v. %s", err, out)
}

// Install Appx anew
cmd = powershellf(ctx, "Add-AppxPackage %q", filepath.Join(buildPath, "windows-agent", "UbuntuProForWindows_*.msixbundle"))
if out, err := cmd.CombinedOutput(); err != nil {
return "", fmt.Errorf("could not install pre-built AppxPackage: %v. %s", err, out)
// Locate the Appx package and store the path in global variable so that we can
// reinstall it before every test
result, err := globSingleResult(filepath.Join(buildPath, "windows-agent", "UbuntuProForWindows_*.msixbundle"))
if err != nil {
return "", fmt.Errorf("could not locate MSIX: %v", err)
}
msixPath = result

// Locate WSL-Pro-Service (it'll be installed later into the distros)
debPath = filepath.Join(buildPath, "wsl-pro-service")
_, err = locateWslProServiceDeb(ctx, debPath)
_, err = locateWslProServiceDeb(debPath)
if err != nil {
return "", fmt.Errorf("could not localte pre-built WSL-Pro-Service: %v", err)
return "", fmt.Errorf("could not locate pre-built WSL-Pro-Service: %v", err)
}

return debPath, err
Expand All @@ -133,13 +133,24 @@ func buildProject(ctx context.Context) (debPath string, err error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()

debPath, err = os.MkdirTemp(os.TempDir(), "WslProService")
buildPath, err := os.MkdirTemp(os.TempDir(), "UP4W-E2E-build")
if err != nil {
return "", fmt.Errorf("could not create temporary directory for debian artifacts")
return "", fmt.Errorf("could not create temporary directory for build artifacts")
}

debPath = filepath.Join(buildPath, "wsl-pro-service")
winPath := filepath.Join(buildPath, "windows-agent")

if err := os.MkdirAll(debPath, 0600); err != nil {
return "", fmt.Errorf("could not create directory for debian artifacts")
}

if err := os.MkdirAll(winPath, 0600); err != nil {
return "", fmt.Errorf("could not create directory for MSIX artifacts")
}

jobs := map[string]*exec.Cmd{
"Build Windows Agent": powershellf(ctx, `..\tools\build\build-appx.ps1 -Mode end_to_end_tests`),
"Build Windows Agent": powershellf(ctx, `..\tools\build\build-appx.ps1 -Mode end_to_end_tests -OutputDir %q`, winPath),
"Build Wsl Pro Service": powershellf(ctx, `..\tools\build\build-deb.ps1 -OutputDir %q`, debPath),
}

Expand Down Expand Up @@ -178,8 +189,15 @@ func buildProject(ctx context.Context) (debPath string, err error) {
return "", fmt.Errorf("could not build project: %v", err)
}

// Locate the Appx package and store the path in global variable so that we can
// reinstall it before every test
path, err := globSingleResult(filepath.Join(winPath, "UbuntuProForWindows_*.msixbundle"))
if err != nil {
return "", fmt.Errorf("could not locate Appx: %v", err)
}

log.Println("Project built")
return debPath, nil
return path, nil
}

// assertAppxInstalled returns an error if the provided Appx is not installed.
Expand All @@ -197,17 +215,12 @@ func assertAppxInstalled(ctx context.Context, appx string) error {
}

// locateWslProServiceDeb locates the WSL pro service at the repository root and returns its absolute path.
func locateWslProServiceDeb(ctx context.Context, path string) (debPath string, err error) {
func locateWslProServiceDeb(path string) (debPath string, err error) {
defer decorate.OnError(&err, "could not locate wsl-pro-service deb package")

out, err := powershellf(ctx, `(Get-ChildItem -Path "%s/wsl-pro-service_*.deb").FullName`, path).CombinedOutput()
path, err = globSingleResult(filepath.Join(path, "wsl-pro-service_*.deb"))
if err != nil {
return "", fmt.Errorf("could not read expected location: %v. %s", err, out)
}

debPath = strings.TrimSpace(string(out))
if debPath == "" {
return "", errors.New("Wsl Pro Service is not built")
return "", err
}

debPath, err = filepath.Abs(debPath)
Expand Down Expand Up @@ -302,6 +315,10 @@ func filesToCleanUp() ([]string, error) {
// assertCleanRegistry returns error if registry key 'UbuntuPro' exists.
// If safety checks are overridden, then the key is removed and no error is returned.
func assertCleanRegistry() error {
if os.Getenv(overrideSafety) != "" {
return cleanupRegistry()
}

k, err := registry.OpenKey(registry.CURRENT_USER, registryPath, registry.READ)
if errors.Is(err, registry.ErrNotExist) {
// Key does not exist, as expected
Expand All @@ -314,11 +331,6 @@ func assertCleanRegistry() error {

k.Close()

// Key exists: this is probably running outside of a clean runner
if os.Getenv(overrideSafety) != "" {
return cleanupRegistry()
}

// Protect unsuspecting users
return fmt.Errorf(`UbuntuPro registry key should not exist. Remove it from your machine `+
`to agree to run this potentially destructive test. It can be located at `+
Expand Down Expand Up @@ -384,7 +396,7 @@ func generateTestImage(ctx context.Context, sourceDistro, wslProServiceDebPath s
// From now on, all cleanups must be deferred because the distro
// must be unregistered before removing the directory it is in.

debPath, err := locateWslProServiceDeb(ctx, wslProServiceDebPath)
debPath, err := locateWslProServiceDeb(wslProServiceDebPath)
if err != nil {
return "", nil, err
}
Expand Down Expand Up @@ -434,3 +446,21 @@ func assertDistroUnregistered(d gowsl.Distro) error {

return nil
}

// globSingleResult searches for the specified glob pattern and returns success
// if, and only if, there is only one file matching it.
func globSingleResult(pattern string) (string, error) {
candidates, err := filepath.Glob(pattern)
if err != nil {
return "", fmt.Errorf("could not search pattern %s: %v", pattern, err)
}

if len(candidates) == 0 {
return "", fmt.Errorf("no file matches pattern %s", pattern)
}
if len(candidates) > 1 {
return "", fmt.Errorf("multiple file match pattern %s:\n - %s", pattern, strings.Join(candidates, "\n - "))
}

return candidates[0], nil
}
17 changes: 17 additions & 0 deletions end-to-end/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ func testSetup(t *testing.T) {
err = stopAgent(ctx)
require.NoError(t, err, "Setup: could not stop the agent")

err = reinstallMSIX(ctx, msixPath)
require.NoError(t, err, "Setup: could not reinstall the agent")

err = assertCleanRegistry()
require.NoError(t, err, "Setup: registry is polluted, potentially by a previous test")

Expand Down Expand Up @@ -235,3 +238,17 @@ func logWindowsAgentOnError(t *testing.T, ctx context.Context) {

t.Logf("Windows Agent's logs:\n%s\n", out)
}

func reinstallMSIX(ctx context.Context, path string) error {
cmd := powershellf(ctx, "Get-AppxPackage %q | Remove-AppxPackage", up4wAppxPackage)
if out, err := cmd.CombinedOutput(); err != nil {
// (Probably because it was not installed)
log.Printf("Could not remove old AppxPackage: %v. %s", err, out)
}

if out, err := powershellf(ctx, "Add-AppxPackage %q", path).CombinedOutput(); err != nil {
return fmt.Errorf("could not install AppxPackage: %v. %s", err, out)
}

return nil
}
9 changes: 8 additions & 1 deletion tools/build/build-appx.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

param (
[Parameter(Mandatory = $true, HelpMessage = "production, end_to_end_tests.")]
[string]$mode,

[string]$mode
[Parameter(Mandatory = $false, HelpMessage = "A directory were the MSIX and the certificate will be copied to")]
[string]$OutputDir
)

function Start-VsDevShell {
Expand Down Expand Up @@ -78,6 +80,11 @@ function Install-Appx {
| Select-Object -last 1 `
)

if ( "${OutputDir}" -ne "" ) {
Copy-Item -Path "${artifacts}/*.cer" -Destination "${OutputDir}"
Copy-Item -Path "${artifacts}/*.msixbundle" -Destination "${OutputDir}"
}

If ($mode -ne 'production') {
Add-AppxPackage "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows Kits\10\ExtensionSDKs\Microsoft.VCLibs.Desktop\14.0\Appx\Debug\x64\Microsoft.VCLibs.x64.Debug.14.00.Desktop.appx"
}
Expand Down

0 comments on commit 939dbeb

Please sign in to comment.