Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 0 additions & 64 deletions .github/workflows/build-and-release.yml

This file was deleted.

49 changes: 49 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: tests

# Runs the PowerShell unit/integration tests on Windows and verifies the single-file build is in
# sync. No compiling, no auto-releasing -- releases are cut by hand. Replaces the old
# "Compile and Release" workflow, which built a since-deleted Magisk.cpp and could clobber releases.

on:
push:
branches: [ main ]
paths-ignore:
- '**.md'
- 'docs/**'
- 'archive/**'
- 'recovered/**'
- 'LICENSE'
pull_request:
branches: [ main ]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: tests-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: Windows PowerShell tests
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v5

# The .cmd ships the engine + orchestrator embedded; make sure they match tools\*.ps1.
- name: Embedded build in sync with tools/
shell: cmd
run: powershell -NoProfile -ExecutionPolicy Bypass -File tests\Check-Embedded-Sync.ps1

# Core engine: integrity patch, .bstk disk-mode, conf root flags, su round-trip, bootstrap.
# (Invoked via powershell.exe -File exactly as blueStackRoot.cmd does, i.e. Windows PowerShell 5.1.)
- name: Engine unit / integration tests
shell: cmd
run: powershell -NoProfile -ExecutionPolicy Bypass -File tests\Run-Tests.ps1

# Nothing-hardcoded guarantees: custom install/data paths + adb port (5555 is not assumed).
- name: Path + adb-port resolution tests
shell: cmd
run: powershell -NoProfile -ExecutionPolicy Bypass -File tests\Run-Resolve-Tests.ps1
46 changes: 46 additions & 0 deletions tests/Check-Embedded-Sync.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<#
Check-Embedded-Sync.ps1 -- CI guard for the single-file build.

blueStackRoot.cmd carries the engine and the Magisk orchestrator embedded between marker lines.
They are authored in tools\bsr_engine.ps1 / tools\bsr_magisk.ps1 and spliced in by tools\reembed.ps1.
If someone edits a tools\*.ps1 without re-running reembed, the .cmd silently ships stale logic.

This test extracts the embedded blocks exactly like the .cmd does at run time and compares them to
the tools\ sources (newline-normalised). Exit code 1 on any drift, 0 when in sync.

Usage: powershell -NoProfile -ExecutionPolicy Bypass -File tests\Check-Embedded-Sync.ps1
#>
$ErrorActionPreference = 'Stop'
$here = if ($PSScriptRoot) { $PSScriptRoot } elseif ($PSCommandPath) { Split-Path -Parent $PSCommandPath } else { (Get-Location).Path }
$repo = Split-Path -Parent $here
$cmd = Join-Path $repo 'blueStackRoot.cmd'
if (-not (Test-Path -LiteralPath $cmd)) { throw "blueStackRoot.cmd not found: $cmd" }
$t = [IO.File]::ReadAllText($cmd)

function Norm([string]$s) { ($s -replace "`r`n", "`n").TrimEnd("`n", " ", "`t") }
function Extract([string]$tag) {
$b = '__BSR_' + $tag + '_' + 'BEGIN__'; $e = '__BSR_' + $tag + '_' + 'END__'
$i = $t.IndexOf($b); $j = $t.IndexOf($e)
if ($i -lt 0 -or $j -le $i) { throw "embedded block $tag not found in blueStackRoot.cmd" }
$i = $t.IndexOf([char]10, $i) + 1
return $t.Substring($i, $j - $i)
}

$fail = 0
foreach ($p in @(@('ENGINE', 'tools\bsr_engine.ps1'), @('MAGISK', 'tools\bsr_magisk.ps1'))) {
$src = Join-Path $repo $p[1]
if (-not (Test-Path -LiteralPath $src)) { Write-Host " [FAIL] source missing: $($p[1])" -ForegroundColor Red; $fail++; continue }
$emb = Norm (Extract $p[0])
$on = Norm ([IO.File]::ReadAllText($src))
if ($emb -eq $on) {
Write-Host (" [PASS] {0,-7} embedded == {1} ({2} chars)" -f $p[0], $p[1], $emb.Length) -ForegroundColor Green
} else {
Write-Host (" [FAIL] {0,-7} embedded != {1} (embedded {2}, source {3} chars) -- run tools\reembed.ps1" -f $p[0], $p[1], $emb.Length, $on.Length) -ForegroundColor Red
$fail++
}
}

Write-Host ""
if ($fail) { Write-Host "RESULT: embedded blocks OUT OF SYNC ($fail) -- re-run tools\reembed.ps1 and commit blueStackRoot.cmd" -ForegroundColor Red; exit 1 }
Write-Host "RESULT: embedded blocks in sync with tools\ sources" -ForegroundColor Green
exit 0
14 changes: 13 additions & 1 deletion tests/Run-Resolve-Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ function Eq([string]$name, $expected, $actual) { Ok $name ("$expected" -eq "$act
# Run the engine as a child process (exactly how blueStackRoot.cmd calls it).
function Eng([string[]]$a) { & powershell -NoProfile -ExecutionPolicy Bypass -File $Engine @a 2>&1 }

# Expand any 8.3 short path component (e.g. CI's C:\Users\RUNNER~1\... for 'runneradmin') to its long
# form. The engine resolves the on-disk Root.vhd, so it returns the long path; without this the expected
# string (built from $env:TEMP, which the runner reports short) would mismatch purely on 8.3 vs long.
Add-Type -ErrorAction SilentlyContinue -Name Native -Namespace BSR -MemberDefinition '
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public static extern uint GetLongPathName(string lpszShortPath, System.Text.StringBuilder lpszLongPath, uint cchBuffer);'
function Long([string]$p) {
if (-not $p) { return $p }
try { $sb = New-Object System.Text.StringBuilder 1024; $n = [BSR.Native]::GetLongPathName($p, $sb, 1024); if ($n -gt 0 -and $n -lt 1024) { return $sb.ToString() } } catch { }
return $p
}

# ---------------------------------------------------------------------------
# Build a throwaway BlueStacks-shaped DataDir at a NON-default (custom) location.
# ---------------------------------------------------------------------------
Expand All @@ -47,7 +59,7 @@ function New-FakeData([string]$instance, [hashtable]$confKeys, [string]$tag = 'r
'<HardDisk format="VHD" location="Root.vhd" type="Readonly"/></HardDisks></MediaRegistry></Machine></VirtualBox>'
[IO.File]::WriteAllText((Join-Path $eng "$instance.bstk"), $bstk)
[IO.File]::WriteAllBytes((Join-Path $eng 'Root.vhd'), (New-Object byte[] 64))
return $root
return (Long $root) # long-path form so expected paths match the engine's disk-resolved VHD path
}
function Resolve-Map([string]$dataDir, [string]$base) {
$out = Eng @('-Action', 'Resolve', '-DataDir', $dataDir, '-Base', $base)
Expand Down
6 changes: 6 additions & 0 deletions todolist.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
column below; coloured via PowerShell `Write-Host` so box-drawing renders regardless of code page.
Typos re-prompt instantly (`:prompt`) instead of a full redraw. (Menu lives in the batch portion, so
no re-embed is needed for these changes.)
- [x] **CI replaced:** dropped the bogus `Compile and Release` workflow (it `g++`-compiled a since-deleted
`Magisk.cpp` -- always failing -- and its release step would have clobbered hand-cut releases with
nonexistent `magisk.exe`/`NewblueStacksRoot.cmd`). New `.github/workflows/tests.yml` runs on push/PR
to `main`: `tests/Run-Tests.ps1` (28) + `tests/Run-Resolve-Tests.ps1` (22) on windows-latest, plus a
new `tests/Check-Embedded-Sync.ps1` guarding that the embedded engine/orchestrator still match
`tools\bsr_engine.ps1`/`bsr_magisk.ps1`. No auto-compile, no auto-release (releases are cut by hand).

## Open / nice-to-have
- [ ] optional: dedicated per-instance Root.vhd (separate VHD + UUID) for a *bit-pristine* `/system` on
Expand Down
Loading