Skip to content
Closed
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
44 changes: 41 additions & 3 deletions dm/ios/tests/test_ipa_unsigned.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""The unsigned IPA of build_ipa.sh: the game files stay out with DM_COPY_ROMFS=NO, and the executable carries the entitlements in an ad-hoc signature.
Only the archive step and the signing step run (a stand-in app, no Xcode or game files)."""
"""The unsigned IPA of build_ipa.sh: the game files stay out with DM_COPY_ROMFS=NO, the executable carries the entitlements in an ad-hoc signature, and the Info.plist names the shared and the game's own URL scheme.
Only the archive step, the signing step and the Info.plist block run (a stand-in app, no Xcode or game files)."""
import os
from pathlib import Path
import plistlib
import shutil
import subprocess
import sys
Expand All @@ -19,13 +20,18 @@
SCRIPT = (REPO / 'dm/ios/tools/build_ipa.sh').read_text()
SIGNING = SCRIPT[SCRIPT.index('# The entitlements of an unsigned IPA'):SCRIPT.index('\nP=Payload/DmIOS.app\n')]
PACKING = SCRIPT[SCRIPT.index('\nP=Payload/DmIOS.app\n'):]
SCHEMES = SCRIPT[SCRIPT.index('# Game handoff: register the shared scheme'):SCRIPT.index('# DM_METAL_CAPTURE=1')]
PLIST = ('<?xml version="1.0" encoding="UTF-8"?>\n'
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
'<plist version="1.0"><dict><key>CFBundleIdentifier</key><string>dev.nxnative.fixture</string></dict></plist>\n')
PREAMBLE = 'set -u\nt() { :; }; die() { echo "$*" >&2; exit 1; }\ngp() { python3 "$PROFILE_TOOL" "$GAME" "$1"; }\n'
CAN_SIGN = sys.platform == 'darwin' and shutil.which('codesign') and shutil.which('cc')


def run_step(script, root, **extra):
env = {k: v for k, v in os.environ.items() if not k.startswith('DM_') and k not in ('IOS_PULL', 'AOC', 'PSO')}
env.update(GAME=GAME, DM=str(root / 'dm'), PROFILE_TOOL=str(REPO / 'dm/games/game.py'), **extra)
env.update({'GAME': GAME, 'DM': str(root / 'dm'), 'PROFILE_TOOL': str(REPO / 'dm/games/game.py')})
env.update(extra)
return subprocess.run(['/bin/bash', '-c', PREAMBLE + script], cwd=root, env=env, capture_output=True, text=True)


Expand Down Expand Up @@ -97,5 +103,37 @@ def test_executable_carries_the_entitlements(self):
self.assertEqual('com.apple.developer.kernel.increased-memory-limit' in shown.stdout + shown.stderr, expected)


class UrlSchemeTests(unittest.TestCase):
"""The Info.plist block build_ipa.sh runs after xcodegen: the shared scheme and this game's own."""

def plist(self, root, game_id=GAME):
(root / 'Gen').mkdir()
path = root / 'Gen/Info.plist'
path.write_text(PLIST)
return path, run_step(SCHEMES, root, GAME=game_id)

def test_one_entry_names_the_shared_and_the_game_scheme(self):
for game_id in (GAME, '0100A6301214E000'):
with self.subTest(game=game_id), tempfile.TemporaryDirectory() as temporary:
path, result = self.plist(Path(temporary), game_id)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
plist = plistlib.loads(path.read_bytes())
self.assertEqual(plist['CFBundleURLTypes'], [{
'CFBundleURLName': 'dev.nxnative',
'CFBundleURLSchemes': ['nxnative', 'nxnative-' + game_id.lower()]}])
self.assertEqual(plist['CFBundleIdentifier'], 'dev.nxnative.fixture') # nothing else is touched

def test_a_plist_that_already_names_schemes_stops_the_build(self):
with tempfile.TemporaryDirectory() as temporary:
root = Path(temporary)
path, result = self.plist(root)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
before = path.read_bytes()
result = run_step(SCHEMES, root)
self.assertNotEqual(result.returncode, 0) # die "URL schemes": no silent second entry for one bundle
self.assertIn('URL schemes', result.stderr)
self.assertEqual(path.read_bytes(), before)


if __name__ == '__main__':
unittest.main()
8 changes: 8 additions & 0 deletions dm/ios/tools/build_ipa.sh
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ xcodegen generate -q > /dev/null || die "xcodegen"
COMMIT=$(git -C "$DM" rev-parse --short=12 HEAD 2> /dev/null) && { [ -z "$(git -C "$DM" status --porcelain --untracked-files=no 2> /dev/null)" ] || COMMIT=$COMMIT+dirty
/usr/libexec/PlistBuddy -c "Add :DMCommit string $COMMIT" Gen/Info.plist > /dev/null || die "DMCommit"; t "source: $COMMIT"; }
case "$MSLDIR" in b-*) /usr/libexec/PlistBuddy -c "Add :DMChain string ${MSLDIR#b-}" Gen/Info.plist > /dev/null || die "DMChain";; esac
# Game handoff: register the shared scheme and this game's own scheme
# (nxnative-<title id>) so a launcher can detect and open exactly this game.
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes array" Gen/Info.plist > /dev/null || die "URL schemes"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0 dict" Gen/Info.plist > /dev/null || die "URL schemes"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLName string dev.nxnative" Gen/Info.plist > /dev/null || die "URL schemes"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLSchemes array" Gen/Info.plist > /dev/null || die "URL schemes"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLSchemes:0 string nxnative" Gen/Info.plist > /dev/null || die "URL schemes"
/usr/libexec/PlistBuddy -c "Add :CFBundleURLTypes:0:CFBundleURLSchemes:1 string nxnative-$(echo "$GAME" | tr 'A-Z' 'a-z')" Gen/Info.plist > /dev/null || die "URL schemes"
# DM_METAL_CAPTURE=1: a development build that may write GPU frame captures (MetalCaptureEnabled; the host's DM_GPU_CAPTURE switch writes them to Documents/gpu_captures)
if [ "${DM_METAL_CAPTURE:-0}" = 1 ]; then /usr/libexec/PlistBuddy -c "Add :MetalCaptureEnabled bool true" Gen/Info.plist > /dev/null || die "MetalCaptureEnabled"; t "Metal frame capture: enabled (DM_METAL_CAPTURE=1)"; fi
RP=; if [ -n "${PROGRAMS_TSV:-}" ]; then # a game of several programs: each program's files, which the Xcode build phase copies under p<index> as the IPA has them (stage_resources.sh)
Expand Down
Loading