diff --git a/.env.local.example b/.env.local.example index bed23ea..879acdd 100644 --- a/.env.local.example +++ b/.env.local.example @@ -1,4 +1,4 @@ -# uatu release credentials (local dev only). +# sanderling release credentials (local dev only). # # Copy to `.env.local` (gitignored) and fill in values ONLY if you need to # fire a real release from your laptop. Day-to-day work and the `release-cli` diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff197d6..eb04614 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,10 +55,10 @@ jobs: gradle-${{ runner.os }}- - name: Publish to Maven Central - run: ./gradlew :sdk-android:publishAndReleaseToMavenCentral -Puatu.version=${{ steps.ver.outputs.version }} + run: ./gradlew :sdk-android:publishAndReleaseToMavenCentral -Psanderling.version=${{ steps.ver.outputs.version }} release-npm: - name: Publish @uatu/spec to npm + name: Publish @sanderling/spec to npm runs-on: ubuntu-latest env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -91,7 +91,7 @@ jobs: - name: Publish working-directory: pkg/spec-api - # npm tag pre-releases (e.g. 0.1.0-rc1) as "next" so npm install @uatu/spec + # npm tag pre-releases (e.g. 0.1.0-rc1) as "next" so npm install @sanderling/spec # keeps resolving the latest stable. run: | if [[ "${{ steps.ver.outputs.version }}" == *-* ]]; then @@ -101,7 +101,7 @@ jobs: fi release-cli: - name: Publish uatu CLI to GitHub Releases + name: Publish sanderling CLI to GitHub Releases runs-on: ubuntu-latest permissions: contents: write diff --git a/.gitignore b/.gitignore index 776cc05..daca44a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ local.properties *.test *.out -# Uatu runs +# Sanderling runs /runs/ # Node @@ -27,7 +27,7 @@ node_modules/ .env .env.local -# Sidecar fat JAR. Build artifact copied in by `make uatu` before +# Sidecar fat JAR. Build artifact copied in by `make sanderling` before # `go build -tags withsidecar`. Never commit: it's ~130 MB. internal/sidecar/assets/sidecar-all.jar diff --git a/.goreleaser.yaml b/.goreleaser.yaml index dac6cdc..1647206 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,6 +1,6 @@ version: 2 -project_name: uatu +project_name: sanderling before: hooks: @@ -11,9 +11,9 @@ before: - sh -c 'mkdir -p internal/sidecar/assets && cp sidecar/build/libs/sidecar-all.jar internal/sidecar/assets/sidecar-all.jar' builds: - - id: uatu - main: ./cmd/uatu - binary: uatu + - id: sanderling + main: ./cmd/sanderling + binary: sanderling env: - CGO_ENABLED=0 flags: @@ -28,11 +28,11 @@ builds: - arm64 archives: - - id: uatu + - id: sanderling ids: - - uatu + - sanderling formats: [tar.gz] - name_template: "uatu_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + name_template: "sanderling_{{ .Version }}_{{ .Os }}_{{ .Arch }}" files: - README.md - LICENSE* @@ -59,6 +59,6 @@ changelog: release: github: owner: priyanshujain - name: uatu + name: sanderling draft: false prerelease: auto diff --git a/Makefile b/Makefile index 0329f0f..7277e25 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ GO_PACKAGES := ./... SIDECAR_JAR := sidecar/build/libs/sidecar-all.jar SIDECAR_EMBED := internal/sidecar/assets/sidecar-all.jar SDK_AAR := sdk/android/build/outputs/aar/sdk-android-release.aar -UATU_BIN := bin/uatu +SANDERLING_BIN := bin/sanderling DOCS_SRC := $(shell find docs -type f -name '*.md' -not -path 'docs/_*') DOCS_OUT := $(patsubst docs/%.md,build/site/%.html,$(DOCS_SRC)) @@ -18,7 +18,7 @@ DOCS_TEMPLATE := docs/_template/page.html INSPECT_DIST := internal/inspect/dist WEB_DIST := web/dist -.PHONY: bootstrap proto sidecar sdk-android sdk-android-publish uatu install test test-go test-kotlin test-spec-api web-typecheck web-build web-dev inspect-dev docs clean release-cli release-android-local release-npm-dry +.PHONY: bootstrap proto sidecar sdk-android sdk-android-publish sanderling install test test-go test-kotlin test-spec-api web-typecheck web-build web-dev inspect-dev docs clean release-cli release-android-local release-npm-dry bootstrap: $(GO) mod download @@ -37,17 +37,17 @@ sdk-android: sdk-android-publish: ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:publishToMavenLocal -uatu: $(UATU_BIN) +sanderling: $(SANDERLING_BIN) -$(UATU_BIN): $(SIDECAR_EMBED) web-build +$(SANDERLING_BIN): $(SIDECAR_EMBED) web-build mkdir -p bin - $(GO) build -tags withsidecar -o $(UATU_BIN) ./cmd/uatu + $(GO) build -tags withsidecar -o $(SANDERLING_BIN) ./cmd/sanderling -# Installs `uatu` into $GOBIN (or $GOPATH/bin) so it's directly on PATH for +# Installs `sanderling` into $GOBIN (or $GOPATH/bin) so it's directly on PATH for # anyone with a standard Go toolchain setup. install: $(SIDECAR_EMBED) web-build - $(GO) install -tags withsidecar ./cmd/uatu - @dest="$$($(GO) env GOBIN)"; [ -n "$$dest" ] || dest="$$($(GO) env GOPATH)/bin"; echo "installed uatu to $$dest" + $(GO) install -tags withsidecar ./cmd/sanderling + @dest="$$($(GO) env GOBIN)"; [ -n "$$dest" ] || dest="$$($(GO) env GOPATH)/bin"; echo "installed sanderling to $$dest" web-build: cd web && bun install --frozen-lockfile && bun run build @@ -59,7 +59,7 @@ web-dev: cd web && bun run dev inspect-dev: $(SIDECAR_EMBED) - $(GO) run -tags withsidecar ./cmd/uatu inspect --dev + $(GO) run -tags withsidecar ./cmd/sanderling inspect --dev web-typecheck: cd web && bun install --frozen-lockfile && bun run typecheck @@ -109,7 +109,7 @@ release-cli: $(SIDECAR_JAR) release-android-local: @if [ -f .env.local ]; then set -a; . ./.env.local; set +a; fi; \ - ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:publishToMavenLocal -Puatu.version=0.0.0-local + ANDROID_HOME=$(ANDROID_HOME) $(GRADLE) :sdk-android:publishToMavenLocal -Psanderling.version=0.0.0-local release-npm-dry: cd pkg/spec-api && npm ci && npm run build && npm pack --dry-run diff --git a/README.md b/README.md index 9d858f0..abbedaf 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# uatu +# sanderling Autonomous property-based testing for mobile apps. Specs in TypeScript. Core in Go. Drives the app under test through Maestro and an in-app SDK. -> Alpha. Android emulator only. Full scope in the [v0.1.0 roadmap](https://github.com/priyanshujain/uatu/issues/4). +> Alpha. Android emulator only. Full scope in the [v0.1.0 roadmap](https://github.com/priyanshujain/sanderling/issues/4). ## Docs -- [Getting started](https://priyanshujain.github.io/uatu/manual/getting-started.html) -- [Writing specs](https://priyanshujain.github.io/uatu/manual/writing-specs.html) -- [`uatu inspect` UI](https://priyanshujain.github.io/uatu/manual/inspect.html) -- [Example](https://github.com/priyanshujain/uatu/tree/master/examples/folio) -- [Architecture](https://priyanshujain.github.io/uatu/development/architecture.html) +- [Getting started](https://priyanshujain.github.io/sanderling/manual/getting-started.html) +- [Writing specs](https://priyanshujain.github.io/sanderling/manual/writing-specs.html) +- [`sanderling inspect` UI](https://priyanshujain.github.io/sanderling/manual/inspect.html) +- [Example](https://github.com/priyanshujain/sanderling/tree/master/examples/folio) +- [Architecture](https://priyanshujain.github.io/sanderling/development/architecture.html) -After a `uatu test` run, browse traces locally with `uatu inspect`. It opens a web UI for stepping through actions, screenshots, snapshots, residual formulas, and exceptions. +After a `sanderling test` run, browse traces locally with `sanderling inspect`. It opens a web UI for stepping through actions, screenshots, snapshots, residual formulas, and exceptions. diff --git a/cmd/internal-tools/bundle-check/main.go b/cmd/internal-tools/bundle-check/main.go index a30111b..b8821c1 100644 --- a/cmd/internal-tools/bundle-check/main.go +++ b/cmd/internal-tools/bundle-check/main.go @@ -5,7 +5,7 @@ import ( "os" "path/filepath" - "github.com/priyanshujain/uatu/internal/bundler" + "github.com/priyanshujain/sanderling/internal/bundler" ) func main() { @@ -31,8 +31,8 @@ func main() { result, err := bundler.Bundle(bundler.Options{ EntryFile: entryFile, Aliases: map[string]string{ - "@uatu/spec": specApiPath, - "@uatu/spec/defaults/properties": defaultPropertiesPath, + "@sanderling/spec": specApiPath, + "@sanderling/spec/defaults/properties": defaultPropertiesPath, }, }) if err != nil { diff --git a/cmd/internal-tools/hier-check/main.go b/cmd/internal-tools/hier-check/main.go index fc674f3..26089c0 100644 --- a/cmd/internal-tools/hier-check/main.go +++ b/cmd/internal-tools/hier-check/main.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/priyanshujain/uatu/internal/hierarchy" + "github.com/priyanshujain/sanderling/internal/hierarchy" ) func main() { diff --git a/cmd/uatu/android_env.go b/cmd/sanderling/android_env.go similarity index 100% rename from cmd/uatu/android_env.go rename to cmd/sanderling/android_env.go diff --git a/cmd/uatu/android_env_test.go b/cmd/sanderling/android_env_test.go similarity index 86% rename from cmd/uatu/android_env_test.go rename to cmd/sanderling/android_env_test.go index dd9e532..189ed12 100644 --- a/cmd/uatu/android_env_test.go +++ b/cmd/sanderling/android_env_test.go @@ -31,18 +31,18 @@ func TestParseAdbDevices_Empty(t *testing.T) { func TestParseAVDList_DropsInfoLines(t *testing.T) { output := `INFO | Storing crashdata in: /tmp/x Medium_Phone_API_36.0 -uatu_test +sanderling_test ` got := parseAVDList(output) - want := []string{"Medium_Phone_API_36.0", "uatu_test"} + want := []string{"Medium_Phone_API_36.0", "sanderling_test"} if !reflect.DeepEqual(got, want) { t.Fatalf("got %v, want %v", got, want) } } func TestPickAVD_ExplicitName(t *testing.T) { - got, err := pickAVD("Pixel_7", []string{"Pixel_7", "uatu_test"}) + got, err := pickAVD("Pixel_7", []string{"Pixel_7", "sanderling_test"}) if err != nil { t.Fatal(err) } @@ -59,12 +59,12 @@ func TestPickAVD_ExplicitMissing(t *testing.T) { } func TestPickAVD_SingleAvailable(t *testing.T) { - got, err := pickAVD("", []string{"uatu_test"}) + got, err := pickAVD("", []string{"sanderling_test"}) if err != nil { t.Fatal(err) } - if got != "uatu_test" { - t.Fatalf("got %q, want uatu_test", got) + if got != "sanderling_test" { + t.Fatalf("got %q, want sanderling_test", got) } } diff --git a/cmd/uatu/doctor.go b/cmd/sanderling/doctor.go similarity index 96% rename from cmd/uatu/doctor.go rename to cmd/sanderling/doctor.go index 4e32c02..2eb93a7 100644 --- a/cmd/uatu/doctor.go +++ b/cmd/sanderling/doctor.go @@ -11,7 +11,7 @@ import ( "strconv" "time" - "github.com/priyanshujain/uatu/internal/sidecar" + "github.com/priyanshujain/sanderling/internal/sidecar" ) type doctorCheck struct { @@ -30,7 +30,7 @@ func defaultDoctorChecks() []doctorCheck { func checkSidecarJAR(_ context.Context) error { if sidecar.IsPlaceholder() { - return fmt.Errorf("placeholder JAR embedded; run `make sidecar && make uatu` to embed the real fat JAR") + return fmt.Errorf("placeholder JAR embedded; run `make sidecar && make sanderling` to embed the real fat JAR") } if sidecar.EmbeddedSize() == 0 { return fmt.Errorf("embedded JAR is empty") diff --git a/cmd/uatu/doctor_test.go b/cmd/sanderling/doctor_test.go similarity index 100% rename from cmd/uatu/doctor_test.go rename to cmd/sanderling/doctor_test.go diff --git a/cmd/uatu/inspect.go b/cmd/sanderling/inspect.go similarity index 94% rename from cmd/uatu/inspect.go rename to cmd/sanderling/inspect.go index 965a346..29190b7 100644 --- a/cmd/uatu/inspect.go +++ b/cmd/sanderling/inspect.go @@ -14,7 +14,7 @@ import ( "strconv" "time" - "github.com/priyanshujain/uatu/internal/inspect" + "github.com/priyanshujain/sanderling/internal/inspect" ) type inspectOptions struct { @@ -67,7 +67,7 @@ func runInspect(options inspectOptions, stdout io.Writer) error { } address := listener.Addr().(*net.TCPAddr) browseURL := buildBrowseURL(address, deepLinkID) - fmt.Fprintf(stdout, "uatu inspect listening on %s (runs=%s)\n", browseURL, runsDirectory) + fmt.Fprintf(stdout, "sanderling inspect listening on %s (runs=%s)\n", browseURL, runsDirectory) context, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/cmd/uatu/inspect_test.go b/cmd/sanderling/inspect_test.go similarity index 93% rename from cmd/uatu/inspect_test.go rename to cmd/sanderling/inspect_test.go index 2e4fbdd..dbf2c35 100644 --- a/cmd/uatu/inspect_test.go +++ b/cmd/sanderling/inspect_test.go @@ -36,7 +36,7 @@ func TestParseInspectArgs_RejectsTooManyPositional(t *testing.T) { func TestRun_HelpListsInspectCommand(t *testing.T) { var stdout bytes.Buffer - if err := run([]string{"uatu"}, &stdout, io.Discard); err != nil { + if err := run([]string{"sanderling"}, &stdout, io.Discard); err != nil { t.Fatal(err) } if !strings.Contains(stdout.String(), "inspect") { diff --git a/cmd/uatu/main.go b/cmd/sanderling/main.go similarity index 89% rename from cmd/uatu/main.go rename to cmd/sanderling/main.go index 90de4ec..fb5f5cd 100644 --- a/cmd/uatu/main.go +++ b/cmd/sanderling/main.go @@ -25,18 +25,18 @@ type testOptions struct { output string } -const topUsage = `uatu is a property-based UI fuzzer for mobile apps. +const topUsage = `sanderling is a property-based UI fuzzer for mobile apps. Usage: - uatu [flags] + sanderling [flags] Commands: test Run a spec against an app for a fixed duration. inspect Serve a local web UI for browsing runs/. - doctor Check that the host environment is ready to run uatu. - version Print the uatu version. + doctor Check that the host environment is ready to run sanderling. + version Print the sanderling version. -Run "uatu -h" for command-specific flags. +Run "sanderling -h" for command-specific flags. ` func parseTestArgs(args []string, stderr io.Writer) (testOptions, error) { @@ -100,7 +100,7 @@ func run(args []string, stdout, stderr io.Writer) error { fmt.Fprintln(stdout, Version) return nil default: - return fmt.Errorf("unknown command: %q (try 'uatu help')", args[1]) + return fmt.Errorf("unknown command: %q (try 'sanderling help')", args[1]) } } diff --git a/cmd/uatu/main_test.go b/cmd/sanderling/main_test.go similarity index 92% rename from cmd/uatu/main_test.go rename to cmd/sanderling/main_test.go index ef8265d..607d0e4 100644 --- a/cmd/uatu/main_test.go +++ b/cmd/sanderling/main_test.go @@ -90,10 +90,10 @@ func TestParseTestArgs_RejectsNonAndroidPlatform(t *testing.T) { func TestRun_HelpPrintsUsage(t *testing.T) { var stdout bytes.Buffer - if err := run([]string{"uatu"}, &stdout, io.Discard); err != nil { + if err := run([]string{"sanderling"}, &stdout, io.Discard); err != nil { t.Fatal(err) } - if !strings.Contains(stdout.String(), "uatu ") { + if !strings.Contains(stdout.String(), "sanderling ") { t.Errorf("usage missing, got: %q", stdout.String()) } } @@ -105,7 +105,7 @@ func TestRun_VersionPrintsVersion(t *testing.T) { for _, arg := range []string{"version", "--version", "-v"} { var stdout bytes.Buffer - if err := run([]string{"uatu", arg}, &stdout, io.Discard); err != nil { + if err := run([]string{"sanderling", arg}, &stdout, io.Discard); err != nil { t.Fatalf("%s: %v", arg, err) } if strings.TrimSpace(stdout.String()) != "1.2.3-test" { @@ -115,7 +115,7 @@ func TestRun_VersionPrintsVersion(t *testing.T) { } func TestRun_UnknownCommand(t *testing.T) { - err := run([]string{"uatu", "wat"}, io.Discard, io.Discard) + err := run([]string{"sanderling", "wat"}, io.Discard, io.Discard) if err == nil || !strings.Contains(err.Error(), "unknown command") { t.Fatalf("expected unknown-command error, got %v", err) } @@ -125,7 +125,7 @@ func TestRun_Doctor(t *testing.T) { var stdout bytes.Buffer // Doctor may pass or fail depending on host environment; we just want to // confirm it runs and emits per-check lines. - _ = run([]string{"uatu", "doctor"}, &stdout, io.Discard) + _ = run([]string{"sanderling", "doctor"}, &stdout, io.Discard) output := stdout.String() if !strings.Contains(output, "OK") && !strings.Contains(output, "FAIL") { t.Errorf("doctor output missing OK/FAIL lines: %q", output) @@ -137,7 +137,7 @@ func TestRun_TestSubcommand_PipelineErrors(t *testing.T) { // must surface a specific error rather than panicking — proves the flag // wiring reaches the runner. err := run([]string{ - "uatu", "test", + "sanderling", "test", "--spec", "definitely-missing-spec.ts", "--bundle-id", "com.example", "--avd", "definitely-missing-avd", diff --git a/cmd/uatu/progress_logger.go b/cmd/sanderling/progress_logger.go similarity index 100% rename from cmd/uatu/progress_logger.go rename to cmd/sanderling/progress_logger.go diff --git a/cmd/uatu/test_run.go b/cmd/sanderling/test_run.go similarity index 87% rename from cmd/uatu/test_run.go rename to cmd/sanderling/test_run.go index 5847af2..60486db 100644 --- a/cmd/uatu/test_run.go +++ b/cmd/sanderling/test_run.go @@ -12,17 +12,17 @@ import ( "strconv" "time" - "github.com/priyanshujain/uatu/internal/agent" - "github.com/priyanshujain/uatu/internal/bundler" - "github.com/priyanshujain/uatu/internal/driver/maestro" - "github.com/priyanshujain/uatu/internal/runner" - "github.com/priyanshujain/uatu/internal/sidecar" - "github.com/priyanshujain/uatu/internal/trace" - "github.com/priyanshujain/uatu/internal/verifier" + "github.com/priyanshujain/sanderling/internal/agent" + "github.com/priyanshujain/sanderling/internal/bundler" + "github.com/priyanshujain/sanderling/internal/driver/maestro" + "github.com/priyanshujain/sanderling/internal/runner" + "github.com/priyanshujain/sanderling/internal/sidecar" + "github.com/priyanshujain/sanderling/internal/trace" + "github.com/priyanshujain/sanderling/internal/verifier" ) const ( - socketName = "uatu-agent" + socketName = "sanderling-agent" sidecarStartupTimeout = 30 * time.Second sdkAcceptTimeout = 60 * time.Second ) @@ -35,17 +35,17 @@ func runTestPipeline(ctx context.Context, options testOptions, stdout io.Writer) } aliases := map[string]string{} if specApiPath := resolveSpecAPIPath(options.spec); specApiPath != "" { - aliases["@uatu/spec"] = specApiPath + aliases["@sanderling/spec"] = specApiPath // Also alias published subpath exports so specs importing from - // "@uatu/spec/defaults/properties" resolve to the in-tree source. + // "@sanderling/spec/defaults/properties" resolve to the in-tree source. base := filepath.Dir(specApiPath) - aliases["@uatu/spec/defaults/properties"] = filepath.Join(base, "defaults/properties.ts") + aliases["@sanderling/spec/defaults/properties"] = filepath.Join(base, "defaults/properties.ts") } bundle, err := bundler.Bundle(bundler.Options{ EntryFile: options.spec, Defines: map[string]string{ - "UATU_TEST_PHONE": os.Getenv("UATU_TEST_PHONE"), - "UATU_TEST_OTP": os.Getenv("UATU_TEST_OTP"), + "SANDERLING_TEST_PHONE": os.Getenv("SANDERLING_TEST_PHONE"), + "SANDERLING_TEST_OTP": os.Getenv("SANDERLING_TEST_OTP"), }, Aliases: aliases, }) @@ -54,7 +54,7 @@ func runTestPipeline(ctx context.Context, options testOptions, stdout io.Writer) } fmt.Fprintf(stdout, "bundled spec: %d bytes (sha256=%s)\n", len(bundle.JavaScript), bundle.SHA256[:12]) - sidecarDirectory := filepath.Join(os.TempDir(), "uatu-sidecar") + sidecarDirectory := filepath.Join(os.TempDir(), "sanderling-sidecar") jarPath, err := sidecar.Extract(sidecarDirectory) if err != nil { return fmt.Errorf("extract sidecar: %w", err) @@ -166,7 +166,7 @@ func runTestPipeline(ctx context.Context, options testOptions, stdout io.Writer) Platform: options.platform, BundleID: options.bundleID, StartedAt: time.Now().UTC(), - UatuVersion: "0.0.1", + SanderlingVersion: "0.0.1", } if err := traceWriter.WriteMeta(meta); err != nil { return fmt.Errorf("trace meta: %w", err) @@ -212,8 +212,8 @@ func runTestPipeline(ctx context.Context, options testOptions, stdout io.Writer) } // resolveSpecAPIPath returns the path to pkg/spec-api/src/index.ts inside -// a uatu source checkout, searched upward from the spec file and the cwd. -// Returns "" when not found, in which case esbuild resolves @uatu/spec via +// a sanderling source checkout, searched upward from the spec file and the cwd. +// Returns "" when not found, in which case esbuild resolves @sanderling/spec via // node_modules the way a downstream user's project would. func resolveSpecAPIPath(specPath string) string { candidates := []string{} diff --git a/cmd/uatu/test_run_test.go b/cmd/sanderling/test_run_test.go similarity index 93% rename from cmd/uatu/test_run_test.go rename to cmd/sanderling/test_run_test.go index 490d4e9..28205ca 100644 --- a/cmd/uatu/test_run_test.go +++ b/cmd/sanderling/test_run_test.go @@ -47,6 +47,6 @@ func TestResolveSpecAPIPath_ReturnsEmptyWhenMissing(t *testing.T) { got := resolveSpecAPIPath(specPath) if got != "" { - t.Fatalf("got %q, want empty (no uatu source tree reachable)", got) + t.Fatalf("got %q, want empty (no sanderling source tree reachable)", got) } } diff --git a/docs/_template/page.html b/docs/_template/page.html index c59666d..9c7a44a 100644 --- a/docs/_template/page.html +++ b/docs/_template/page.html @@ -3,14 +3,14 @@ -$if(title)$$title$ · $endif$uatu +$if(title)$$title$ · $endif$sanderling diff --git a/docs/development/architecture.md b/docs/development/architecture.md index 6a145da..6264517 100644 --- a/docs/development/architecture.md +++ b/docs/development/architecture.md @@ -8,7 +8,7 @@ Three processes, two transports. ```mermaid flowchart TB - subgraph Go["uatu (Go)"] + subgraph Go["sanderling (Go)"] Bundler[Bundler
esbuild] --> Verifier[Verifier
goja + LTL] Verifier <--> Runner[Runner] Runner --> Trace[Trace writer
JSONL + PNG] @@ -21,7 +21,7 @@ flowchart TB subgraph Device["Emulator"] subgraph App["Android app (debug)"] - SDK[uatu-sdk
pause / hierarchy
logs / coverage] + SDK[sanderling-sdk
pause / hierarchy
logs / coverage] end end @@ -33,7 +33,7 @@ flowchart TB ## Processes -**uatu (Go).** The top-level binary. Bundles the spec with esbuild, evaluates it in goja, runs the main loop, dispatches actions through the driver, writes the trace. +**sanderling (Go).** The top-level binary. Bundles the spec with esbuild, evaluates it in goja, runs the main loop, dispatches actions through the driver, writes the trace. **Maestro sidecar (JVM).** A Kotlin process that wraps `maestro-client` and exposes a gRPC surface matching the `driver.Driver` interface. Handles UI input, screenshots, the system accessibility tree, and OS-level alerts. diff --git a/docs/development/design-principles.md b/docs/development/design-principles.md index a96b5be..36c066e 100644 --- a/docs/development/design-principles.md +++ b/docs/development/design-principles.md @@ -33,7 +33,7 @@ A 30-minute run is about 10,000 steps. Every step has at least one hierarchy dum A seeded PRNG drives action selection. Spec evaluation is pure given state and snapshots. The bundle hash and seed are recorded in `meta.json`. -uatu does not attempt byte-exact replay. Animation timing, keyboard popup timing, and system daemons are non-deterministic on mobile, and the cost of trying to suppress that is not worth the payoff. Same seed produces a similar trajectory, which is usually enough to reproduce the bug. +sanderling does not attempt byte-exact replay. Animation timing, keyboard popup timing, and system daemons are non-deterministic on mobile, and the cost of trying to suppress that is not worth the payoff. Same seed produces a similar trajectory, which is usually enough to reproduce the bug. ## 6. Fail honest diff --git a/docs/development/index.md b/docs/development/index.md index c8b72f3..a5ac408 100644 --- a/docs/development/index.md +++ b/docs/development/index.md @@ -6,7 +6,7 @@ title: Development - [Design principles](./design-principles.html) - [Architecture](./architecture.html) -- v0.1.0 scope: [issue #4](https://github.com/priyanshujain/uatu/issues/4) +- v0.1.0 scope: [issue #4](https://github.com/priyanshujain/sanderling/issues/4) ## Building the docs site locally diff --git a/docs/index.md b/docs/index.md index 5060221..b280ead 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,12 +1,12 @@ --- -title: uatu +title: sanderling --- -# uatu +# sanderling Autonomous property-based testing for mobile apps. Specs in TypeScript. Core in Go. Drives the app under test through Maestro and an in-app SDK. -Alpha: Android emulator only. Scope of v0.1.0 is tracked in [issue #4](https://github.com/priyanshujain/uatu/issues/4). +Alpha: Android emulator only. Scope of v0.1.0 is tracked in [issue #4](https://github.com/priyanshujain/sanderling/issues/4). ## Manual diff --git a/docs/manual/cli.md b/docs/manual/cli.md index 298d611..5602a14 100644 --- a/docs/manual/cli.md +++ b/docs/manual/cli.md @@ -5,10 +5,10 @@ title: CLI reference # CLI reference ``` -uatu [flags] +sanderling [flags] ``` -## `uatu test` +## `sanderling test` Run a spec against an app for a fixed duration. @@ -23,7 +23,7 @@ Run a spec against an app for a fixed duration. | `--seed` | `0` | PRNG seed. `0` uses a random seed and records it in `meta.json`. | | `--output` | `./runs` | Output directory for traces. | -## `uatu inspect [run-or-runs-dir]` +## `sanderling inspect [run-or-runs-dir]` Serve a local web UI for browsing traces. The positional argument is optional and may point at either a runs directory (the parent of many runs) or a single run directory (auto-detected by the presence of `meta.json`). Defaults to `./runs`. @@ -35,11 +35,11 @@ Serve a local web UI for browsing traces. The positional argument is optional an See [the inspect UI page](inspect.md) for the panel reference and keyboard shortcuts. -## `uatu doctor` +## `sanderling doctor` -Check the host environment for a working uatu setup: Go toolchain, JDK, Maestro availability, emulator reachability, SDK linkage hints. +Check the host environment for a working sanderling setup: Go toolchain, JDK, Maestro availability, emulator reachability, SDK linkage hints. -## `uatu version` +## `sanderling version` Print the CLI version. @@ -49,4 +49,4 @@ Print the CLI version. - `--max-steps` hard cap on step count. - `--exit-on-violation` stop the run on the first property violation. -Tracked in [issue #4](https://github.com/priyanshujain/uatu/issues/4). +Tracked in [issue #4](https://github.com/priyanshujain/sanderling/issues/4). diff --git a/docs/manual/getting-started.md b/docs/manual/getting-started.md index 9c995b1..2fd82f9 100644 --- a/docs/manual/getting-started.md +++ b/docs/manual/getting-started.md @@ -9,10 +9,10 @@ Install the CLI, link the SDK into your debug build, run a spec. ## Prerequisites - An Android emulator with API level 30 or newer. -- The app under test built as a debug variant with the uatu Android SDK linked in. +- The app under test built as a debug variant with the sanderling Android SDK linked in. - `adb` on your PATH. -Run `uatu doctor` to check the host environment. +Run `sanderling doctor` to check the host environment. ## Install @@ -21,15 +21,15 @@ Run `uatu doctor` to check the host environment. macOS arm64: ```sh -curl -L https://github.com/priyanshujain/uatu/releases/latest/download/uatu__darwin_arm64.tar.gz | tar xz -./uatu version +curl -L https://github.com/priyanshujain/sanderling/releases/latest/download/sanderling__darwin_arm64.tar.gz | tar xz +./sanderling version ``` Linux amd64: ```sh -curl -L https://github.com/priyanshujain/uatu/releases/latest/download/uatu__linux_amd64.tar.gz | tar xz -./uatu version +curl -L https://github.com/priyanshujain/sanderling/releases/latest/download/sanderling__linux_amd64.tar.gz | tar xz +./sanderling version ``` Pre-built for `darwin/arm64`, `darwin/amd64`, `linux/amd64`, `linux/arm64`. @@ -37,7 +37,7 @@ Pre-built for `darwin/arm64`, `darwin/amd64`, `linux/amd64`, `linux/arm64`. ### Spec package (npm) ```sh -npm install --save-dev @uatu/spec +npm install --save-dev @sanderling/spec ``` ### Android SDK (Maven Central) @@ -55,14 +55,14 @@ The repo ships a working sample at `examples/folio`. From that directory: ```sh npm install (cd android && ./gradlew installDebug) -uatu test \ +sanderling test \ --spec spec.ts \ --bundle-id app.folio \ --platform android \ --duration 2m ``` -Pass `--avd ` only when no device is connected and you have multiple AVDs; otherwise uatu uses the connected device or boots the single AVD it finds. +Pass `--avd ` only when no device is connected and you have multiple AVDs; otherwise sanderling uses the connected device or boots the single AVD it finds. When the run ends, the trace lands in `runs//`: diff --git a/docs/manual/inspect.md b/docs/manual/inspect.md index d1b701c..788fdea 100644 --- a/docs/manual/inspect.md +++ b/docs/manual/inspect.md @@ -1,13 +1,13 @@ --- -title: uatu inspect +title: sanderling inspect --- -# uatu inspect +# sanderling inspect -`uatu inspect` is a local web UI for exploring runs produced by `uatu test`. It reads `runs//meta.json` and `runs//trace.jsonl` and renders each step with its action, screenshot, snapshots, residual formulas, and exceptions. +`sanderling inspect` is a local web UI for exploring runs produced by `sanderling test`. It reads `runs//meta.json` and `runs//trace.jsonl` and renders each step with its action, screenshot, snapshots, residual formulas, and exceptions. ``` -uatu inspect [run-or-runs-dir] [--port N] [--no-open] [--dev] +sanderling inspect [run-or-runs-dir] [--port N] [--no-open] [--dev] ``` The positional argument can be either a runs directory or a single run directory (auto-detected by the presence of `meta.json`). When omitted, it defaults to `./runs`. @@ -51,11 +51,11 @@ Two-process loop: ``` make web-dev # bun + vite, http://127.0.0.1:5173 -make inspect-dev # uatu inspect --dev, proxies non-API to 5173 +make inspect-dev # sanderling inspect --dev, proxies non-API to 5173 ``` For a single binary with embedded assets: ``` -make uatu # builds web/dist, copies to internal/inspect/dist, then go build +make sanderling # builds web/dist, copies to internal/inspect/dist, then go build ``` diff --git a/docs/manual/runs.md b/docs/manual/runs.md index 1f0441c..4d0e30f 100644 --- a/docs/manual/runs.md +++ b/docs/manual/runs.md @@ -4,14 +4,14 @@ title: Runs # What is a run? -One `uatu test` invocation. Fresh install, spec-driven exploration, then the trace lands in `runs//`. Typically minutes to hours, not seconds. +One `sanderling test` invocation. Fresh install, spec-driven exploration, then the trace lands in `runs//`. Typically minutes to hours, not seconds. A run is not analogous to a unit test. A closer framing is: boot a fuzzer for an hour and see what breaks. Violations are recorded in the trace and exploration continues, so one run can surface many bugs. ## Lifecycle ``` -uatu test --spec spec.ts --bundle-id com.example.app --duration 30m +sanderling test --spec spec.ts --bundle-id com.example.app --duration 30m │ ├── uninstall and reinstall the app (clean slate, every run) ├── boot the sidecar, connect the agent socket @@ -28,7 +28,7 @@ uatu test --spec spec.ts --bundle-id com.example.app --duration 30m ## Why runs are long and linear -uatu does not restart the app every N steps. Each restart throws away two things. +sanderling does not restart the app every N steps. Each restart throws away two things. **Novelty and coverage signal.** The exploration strategy weights actions by whether they reach previously unseen state. Restarting resets that history. @@ -62,4 +62,4 @@ A run ends when either of these happens. The trace is written incrementally, so an interrupted run is still fully inspectable. -Additional termination conditions (`--max-steps`, `--exit-on-violation`, hard crash handling) land in [v0.1.0](https://github.com/priyanshujain/uatu/issues/4). +Additional termination conditions (`--max-steps`, `--exit-on-violation`, hard crash handling) land in [v0.1.0](https://github.com/priyanshujain/sanderling/issues/4). diff --git a/docs/manual/writing-specs.md b/docs/manual/writing-specs.md index 7bb3165..a6781e6 100644 --- a/docs/manual/writing-specs.md +++ b/docs/manual/writing-specs.md @@ -7,7 +7,7 @@ title: Writing specs A spec has three parts: extractors, properties, and actions. ```ts -import { extract, always, actions, weighted, Tap, taps, swipes } from "@uatu/spec"; +import { extract, always, actions, weighted, Tap, taps, swipes } from "@sanderling/spec"; // 1. Extractors pull values from each observed state. const loggedIn = extract((s) => !!s.ax.find("id:home-tab-bar")); @@ -18,7 +18,7 @@ export const properties = { cartNeverNegative: always(() => cartCount.current >= 0), }; -// 3. Actions are a weighted tree of what uatu is allowed to do. +// 3. Actions are a weighted tree of what sanderling is allowed to do. export const actions = weighted( [10, taps], [2, swipes], @@ -45,11 +45,11 @@ interface State { `ax.find("text:Click me")`, `ax.find("id:login-form")`, `ax.findAll("role:todo-row")` are the common accessors. Prefer stable testID-style identifiers over positional selectors, for the same reason you would in Espresso or XCUITest. -`snapshots` is populated by the in-app SDK via `Uatu.extract("name") { value }`. Use it when the UI does not expose a value you need, such as business-logic state or hidden fields. +`snapshots` is populated by the in-app SDK via `Sanderling.extract("name") { value }`. Use it when the UI does not expose a value you need, such as business-logic state or hidden fields. ## Pattern: preconditions (login, onboarding) -uatu has no setup phase and no fixtures. Preconditions are action generators with two properties: +sanderling has no setup phase and no fixtures. Preconditions are action generators with two properties: 1. High weight, so they fire whenever applicable. 2. Gated on a state extractor, so they return an empty tree when not applicable and self-disable once the precondition is met. @@ -145,7 +145,7 @@ When the UI does not expose a value but the app knows it, use the SDK's extracto ```kotlin // in the app (Android) -Uatu.extract("cart_count") { store.cart.size } +Sanderling.extract("cart_count") { store.cart.size } ``` ```ts diff --git a/examples/folio/.gitignore b/examples/folio/.gitignore index 52e8ba2..827413a 100644 --- a/examples/folio/.gitignore +++ b/examples/folio/.gitignore @@ -6,7 +6,7 @@ iosApp/build/ iosApp/iosApp.xcodeproj/ iosApp/iosApp.xcodeproj/** .DS_Store -uatu/node_modules/ -uatu/runs/ +sanderling/node_modules/ +sanderling/runs/ .playwright-mcp/ web-*.png diff --git a/examples/folio/README.md b/examples/folio/README.md index 26f391b..22bdce3 100644 --- a/examples/folio/README.md +++ b/examples/folio/README.md @@ -3,14 +3,14 @@ A minimal Kotlin Multiplatform personal-ledger app: login with demo credentials, create accounts, add credits and debits. Shared UI across Android, iOS, and Web via Compose Multiplatform. Doubles as the example -uatu runs its property-based specs against. +sanderling runs its property-based specs against. ## Stack - Kotlin Multiplatform + Compose Multiplatform (shared UI) - kotlinx.serialization for file-backed persistence - kotlinx.coroutines for state flows -- uatu `sdk-android` for harness integration on Android +- sanderling `sdk-android` for harness integration on Android ## Prerequisites @@ -46,13 +46,13 @@ email: demo@folio.app password: ledger123 ``` -## Run a uatu test (Android) +## Run a sanderling test (Android) ```sh just test ``` -If no device is connected, uatu boots the single AVD it finds. With multiple +If no device is connected, sanderling boots the single AVD it finds. With multiple AVDs, pick one: ```sh @@ -66,13 +66,13 @@ AVD=Pixel_7 DURATION=5m ``` -Traces land in `./uatu/runs//`. +Traces land in `./sanderling/runs//`. -## How it connects to uatu +## How it connects to sanderling -- `composeApp/src/androidMain/.../FolioApplication.kt` calls `Uatu.start(this)` +- `composeApp/src/androidMain/.../FolioApplication.kt` calls `Sanderling.start(this)` and registers snapshot extractors (`logged_in`, `account_count`, `total_balance`, `route`) -- `uatu/spec.ts` imports `@uatu/spec`, reads those snapshots, asserts +- `sanderling/spec.ts` imports `@sanderling/spec`, reads those snapshots, asserts properties, and weights the actions the fuzzer picks from -- `just test` invokes `uatu test` against the installed APK +- `just test` invokes `sanderling test` against the installed APK diff --git a/examples/folio/composeApp/build.gradle.kts b/examples/folio/composeApp/build.gradle.kts index fd96ece..498ba01 100644 --- a/examples/folio/composeApp/build.gradle.kts +++ b/examples/folio/composeApp/build.gradle.kts @@ -10,7 +10,7 @@ plugins { id("app.cash.sqldelight") } -val uatuVersion = findProperty("uatu.version") as String? ?: "0.0.0-dev" +val sanderlingVersion = findProperty("sanderling.version") as String? ?: "0.0.0-dev" val sqldelightVersion = "2.3.2" kotlin { @@ -83,7 +83,7 @@ kotlin { androidMain.dependencies { implementation("androidx.activity:activity-compose:1.13.0") implementation("app.cash.sqldelight:android-driver:$sqldelightVersion") - implementation("io.github.priyanshujain:sdk-android:$uatuVersion") + implementation("io.github.priyanshujain:sdk-android:$sanderlingVersion") } iosMain.dependencies { @@ -101,7 +101,7 @@ android { minSdk = 24 targetSdk = 36 versionCode = 1 - versionName = uatuVersion + versionName = sanderlingVersion } compileOptions { diff --git a/examples/folio/composeApp/src/androidMain/kotlin/app/folio/FolioApplication.kt b/examples/folio/composeApp/src/androidMain/kotlin/app/folio/FolioApplication.kt index 1d90bbf..768c666 100644 --- a/examples/folio/composeApp/src/androidMain/kotlin/app/folio/FolioApplication.kt +++ b/examples/folio/composeApp/src/androidMain/kotlin/app/folio/FolioApplication.kt @@ -11,18 +11,18 @@ import app.folio.navigation.Navigator import app.folio.navigation.Route import app.folio.platform.balanceOf import app.folio.platform.signedAmount -import dev.uatu.sdk.Uatu +import dev.sanderling.sdk.Sanderling class FolioApplication : Application() { override fun onCreate() { super.onCreate() AndroidLedgerContext.context = applicationContext Repository.init() - Uatu.start(this) - Uatu.extract("logged_in") { Repository.session.value != null } - Uatu.extract("account_count") { Repository.accounts.value.size } - Uatu.extract("total_balance") { balanceOf(Repository.transactions.value) } - Uatu.extract("route") { + Sanderling.start(this) + Sanderling.extract("logged_in") { Repository.session.value != null } + Sanderling.extract("account_count") { Repository.accounts.value.size } + Sanderling.extract("total_balance") { balanceOf(Repository.transactions.value) } + Sanderling.extract("route") { when (Navigator.current.value) { Route.Login -> "login" Route.Home -> "home" @@ -31,10 +31,10 @@ class FolioApplication : Application() { is Route.AddTransaction -> "add-transaction" } } - Uatu.extract("auth_status") { + Sanderling.extract("auth_status") { if (Repository.session.value != null) "logged-in" else "logged-out" } - Uatu.extract("accounts") { + Sanderling.extract("accounts") { val txns = Repository.transactions.value Repository.accounts.value.map { a -> val rows = txns.filter { it.accountId == a.id } @@ -46,14 +46,14 @@ class FolioApplication : Application() { ) } } - Uatu.extract("active_account_id") { + Sanderling.extract("active_account_id") { when (val r = Navigator.current.value) { is Route.Ledger -> r.accountId is Route.AddTransaction -> r.accountId else -> null } } - Uatu.extract("ledger_rows") { + Sanderling.extract("ledger_rows") { val active = when (val r = Navigator.current.value) { is Route.Ledger -> r.accountId is Route.AddTransaction -> r.accountId @@ -72,7 +72,7 @@ class FolioApplication : Application() { ) } } - Uatu.extract("ledger_balance") { + Sanderling.extract("ledger_balance") { val active = when (val r = Navigator.current.value) { is Route.Ledger -> r.accountId is Route.AddTransaction -> r.accountId @@ -81,13 +81,13 @@ class FolioApplication : Application() { if (active == null) 0L else balanceOf(Repository.transactions.value.filter { it.accountId == active }) } - Uatu.extract("focused_input") { FocusTracker.current.value } - Uatu.extract("txn_form_type") { AddTransactionUiState.txnFormType.value } - Uatu.extract("txn_form_account_id") { + Sanderling.extract("focused_input") { FocusTracker.current.value } + Sanderling.extract("txn_form_type") { AddTransactionUiState.txnFormType.value } + Sanderling.extract("txn_form_account_id") { (Navigator.current.value as? Route.AddTransaction)?.accountId } - Uatu.extract("login_error") { LoginUiState.loginError.value } - Uatu.extract("add_account_error") { AddAccountUiState.addAccountError.value } - Uatu.extract("txn_error") { AddTransactionUiState.txnError.value } + Sanderling.extract("login_error") { LoginUiState.loginError.value } + Sanderling.extract("add_account_error") { AddAccountUiState.addAccountError.value } + Sanderling.extract("txn_error") { AddTransactionUiState.txnError.value } } } diff --git a/examples/folio/composeApp/src/wasmJsMain/kotlin/app/folio/data/WebLedgerStore.kt b/examples/folio/composeApp/src/wasmJsMain/kotlin/app/folio/data/WebLedgerStore.kt index f31a5fc..0523721 100644 --- a/examples/folio/composeApp/src/wasmJsMain/kotlin/app/folio/data/WebLedgerStore.kt +++ b/examples/folio/composeApp/src/wasmJsMain/kotlin/app/folio/data/WebLedgerStore.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.browser.localStorage -private const val STORAGE_KEY = "uatu.ledger.v1" +private const val STORAGE_KEY = "sanderling.ledger.v1" class WebLedgerStore : LedgerStore { private val _accounts = MutableStateFlow>(emptyList()) diff --git a/examples/folio/gradle.properties b/examples/folio/gradle.properties index 0850e44..bf2e816 100644 --- a/examples/folio/gradle.properties +++ b/examples/folio/gradle.properties @@ -5,6 +5,6 @@ kotlin.code.style=official android.useAndroidX=true android.nonTransitiveRClass=true -# Pin the uatu SDK version consumed by this app. Override with -# `-Puatu.version=`. -uatu.version=0.0.0-dev +# Pin the sanderling SDK version consumed by this app. Override with +# `-Psanderling.version=`. +sanderling.version=0.0.0-dev diff --git a/examples/folio/justfile b/examples/folio/justfile index 8d0860d..989e0ff 100644 --- a/examples/folio/justfile +++ b/examples/folio/justfile @@ -1,11 +1,11 @@ set shell := ["bash", "-cu"] set dotenv-load := true -uatu := env_var_or_default("UATU", "uatu") -avd := env_var_or_default("AVD", "") -duration := env_var_or_default("DURATION", "1m") -seed := env_var_or_default("SEED", "0") -output := env_var_or_default("OUTPUT", justfile_directory() / "uatu" / "runs") +sanderling := env_var_or_default("SANDERLING", "sanderling") +avd := env_var_or_default("AVD", "") +duration := env_var_or_default("DURATION", "1m") +seed := env_var_or_default("SEED", "0") +output := env_var_or_default("OUTPUT", justfile_directory() / "sanderling" / "runs") ios_device := env_var_or_default("IOS_DEVICE", "iPhone 17 Pro") default: @@ -81,7 +81,7 @@ ios: xcrun simctl install booted iosApp/build/Build/Products/Debug-iphonesimulator/iosApp.app xcrun simctl launch booted app.folio -# Run 'uatu test' against the folio app. Uses a connected device if one is +# Run 'sanderling test' against the folio app. Uses a connected device if one is # online, otherwise boots AVD= if provided. test: #!/usr/bin/env bash @@ -90,8 +90,8 @@ test: if [[ -n "{{avd}}" ]]; then avd_flag=(--avd "{{avd}}") fi - "{{uatu}}" test \ - --spec "{{justfile_directory()}}/uatu/spec.ts" \ + "{{sanderling}}" test \ + --spec "{{justfile_directory()}}/sanderling/spec.ts" \ --bundle-id app.folio \ "${avd_flag[@]}" \ --duration "{{duration}}" \ diff --git a/examples/folio/uatu/package-lock.json b/examples/folio/sanderling/package-lock.json similarity index 69% rename from examples/folio/uatu/package-lock.json rename to examples/folio/sanderling/package-lock.json index d2def34..2a94f7f 100644 --- a/examples/folio/uatu/package-lock.json +++ b/examples/folio/sanderling/package-lock.json @@ -6,12 +6,12 @@ "": { "name": "folio", "devDependencies": { - "@uatu/spec": "next" + "@sanderling/spec": "next" } }, - "node_modules/@uatu/spec": { + "node_modules/@sanderling/spec": { "version": "0.0.1-rc3", - "resolved": "https://registry.npmjs.org/@uatu/spec/-/spec-0.0.1-rc3.tgz", + "resolved": "https://registry.npmjs.org/@sanderling/spec/-/spec-0.0.1-rc3.tgz", "integrity": "sha512-mCayssOqM2wfzrQDnFGE8FAlUlDzBl1fx2L/MLDIuPrQHBMlUC350xBB8Z7I/DYI98eCWJMqjtw3iU6yVWKtIQ==", "dev": true, "license": "Apache-2.0" diff --git a/examples/folio/sanderling/package.json b/examples/folio/sanderling/package.json new file mode 100644 index 0000000..458b33a --- /dev/null +++ b/examples/folio/sanderling/package.json @@ -0,0 +1,8 @@ +{ + "name": "folio", + "private": true, + "description": "Minimal sanderling integration example.", + "devDependencies": { + "@sanderling/spec": "next" + } +} diff --git a/examples/folio/uatu/spec.ts b/examples/folio/sanderling/spec.ts similarity index 99% rename from examples/folio/uatu/spec.ts rename to examples/folio/sanderling/spec.ts index e78eac3..2c4ba17 100644 --- a/examples/folio/uatu/spec.ts +++ b/examples/folio/sanderling/spec.ts @@ -13,8 +13,8 @@ import { taps, waitOnce, weighted, -} from "@uatu/spec"; -import { noUncaughtExceptions } from "@uatu/spec/defaults/properties"; +} from "@sanderling/spec"; +import { noUncaughtExceptions } from "@sanderling/spec/defaults/properties"; interface AccountSnapshot { id: string; diff --git a/examples/folio/uatu/package.json b/examples/folio/uatu/package.json deleted file mode 100644 index 4d76e7f..0000000 --- a/examples/folio/uatu/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "folio", - "private": true, - "description": "Minimal uatu integration example.", - "devDependencies": { - "@uatu/spec": "next" - } -} diff --git a/go.mod b/go.mod index cba1918..b424e5c 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/priyanshujain/uatu +module github.com/priyanshujain/sanderling go 1.26.1 diff --git a/gradle.properties b/gradle.properties index 5fdb6dc..3680de2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,6 +10,6 @@ org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true # Single source of truth at release time is the git tag (e.g. v0.1.0 → 0.1.0), -# forwarded via `-Puatu.version=...` or `ORG_GRADLE_PROJECT_uatu.version`. +# forwarded via `-Psanderling.version=...` or `ORG_GRADLE_PROJECT_sanderling.version`. # The default below only applies to untagged local builds. -uatu.version=0.0.0-dev +sanderling.version=0.0.0-dev diff --git a/internal/bundler/bundler_test.go b/internal/bundler/bundler_test.go index 47cf396..47eebf6 100644 --- a/internal/bundler/bundler_test.go +++ b/internal/bundler/bundler_test.go @@ -47,15 +47,15 @@ func TestBundle_ProducesIIFE(t *testing.T) { func TestBundle_InlinesDefines(t *testing.T) { entry := writeFixture(t, "spec.ts", ` - const phone = process.env.UATU_TEST_PHONE; - const otp = process.env.UATU_TEST_OTP; + const phone = process.env.SANDERLING_TEST_PHONE; + const otp = process.env.SANDERLING_TEST_OTP; export const credentials = { phone, otp }; `) result, err := Bundle(Options{ EntryFile: entry, Defines: map[string]string{ - "UATU_TEST_PHONE": "+919876543210", - "UATU_TEST_OTP": "123456", + "SANDERLING_TEST_PHONE": "+919876543210", + "SANDERLING_TEST_OTP": "123456", }, }) if err != nil { @@ -87,13 +87,13 @@ func TestBundle_DeterministicHash(t *testing.T) { func TestBundle_HashChangesWithDefines(t *testing.T) { entry := writeFixture(t, "spec.ts", ` - export const phone = process.env.UATU_TEST_PHONE; + export const phone = process.env.SANDERLING_TEST_PHONE; `) - first, err := Bundle(Options{EntryFile: entry, Defines: map[string]string{"UATU_TEST_PHONE": "1111"}}) + first, err := Bundle(Options{EntryFile: entry, Defines: map[string]string{"SANDERLING_TEST_PHONE": "1111"}}) if err != nil { t.Fatal(err) } - second, err := Bundle(Options{EntryFile: entry, Defines: map[string]string{"UATU_TEST_PHONE": "2222"}}) + second, err := Bundle(Options{EntryFile: entry, Defines: map[string]string{"SANDERLING_TEST_PHONE": "2222"}}) if err != nil { t.Fatal(err) } diff --git a/internal/driver/maestro/client.go b/internal/driver/maestro/client.go index bfc7fd3..7737006 100644 --- a/internal/driver/maestro/client.go +++ b/internal/driver/maestro/client.go @@ -8,8 +8,8 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "github.com/priyanshujain/uatu/internal/driver" - driverpb "github.com/priyanshujain/uatu/proto/driverpb" + "github.com/priyanshujain/sanderling/internal/driver" + driverpb "github.com/priyanshujain/sanderling/proto/driverpb" ) type Client struct { diff --git a/internal/driver/maestro/client_test.go b/internal/driver/maestro/client_test.go index 62b89ba..44b94bd 100644 --- a/internal/driver/maestro/client_test.go +++ b/internal/driver/maestro/client_test.go @@ -10,7 +10,7 @@ import ( "google.golang.org/grpc" - driverpb "github.com/priyanshujain/uatu/proto/driverpb" + driverpb "github.com/priyanshujain/sanderling/proto/driverpb" ) type fakeServer struct { diff --git a/internal/driver/mock/mock.go b/internal/driver/mock/mock.go index afeab14..cecbc38 100644 --- a/internal/driver/mock/mock.go +++ b/internal/driver/mock/mock.go @@ -5,7 +5,7 @@ import ( "sync" "time" - "github.com/priyanshujain/uatu/internal/driver" + "github.com/priyanshujain/sanderling/internal/driver" ) type ActionKind string diff --git a/internal/driver/mock/mock_test.go b/internal/driver/mock/mock_test.go index 2bf94d1..b5a06ca 100644 --- a/internal/driver/mock/mock_test.go +++ b/internal/driver/mock/mock_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/priyanshujain/uatu/internal/driver" + "github.com/priyanshujain/sanderling/internal/driver" ) func TestNew_Defaults(t *testing.T) { diff --git a/internal/inspect/dist/index.html b/internal/inspect/dist/index.html index 17663b0..7c25179 100644 --- a/internal/inspect/dist/index.html +++ b/internal/inspect/dist/index.html @@ -3,7 +3,7 @@ - uatu inspect + sanderling inspect diff --git a/internal/inspect/runs.go b/internal/inspect/runs.go index ee8c809..29e4316 100644 --- a/internal/inspect/runs.go +++ b/internal/inspect/runs.go @@ -12,7 +12,7 @@ import ( "sync" "time" - "github.com/priyanshujain/uatu/internal/trace" + "github.com/priyanshujain/sanderling/internal/trace" ) // Maximum size of a single trace.jsonl line. Hierarchies and snapshots diff --git a/internal/inspect/runs_test.go b/internal/inspect/runs_test.go index 1fe1a10..f3a8b92 100644 --- a/internal/inspect/runs_test.go +++ b/internal/inspect/runs_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/priyanshujain/uatu/internal/trace" + "github.com/priyanshujain/sanderling/internal/trace" ) func TestScan_OrdersByStartedAtDescendingAndCountsViolations(t *testing.T) { diff --git a/internal/inspect/server.go b/internal/inspect/server.go index 85412d0..b75daa3 100644 --- a/internal/inspect/server.go +++ b/internal/inspect/server.go @@ -20,7 +20,7 @@ type ServerOptions struct { DevTarget string } -// Server holds the HTTP handlers for `uatu inspect`. +// Server holds the HTTP handlers for `sanderling inspect`. type Server struct { options ServerOptions cache *Cache diff --git a/internal/inspect/server_test.go b/internal/inspect/server_test.go index cc2c9f5..905bfc2 100644 --- a/internal/inspect/server_test.go +++ b/internal/inspect/server_test.go @@ -13,7 +13,7 @@ import ( "testing" "time" - "github.com/priyanshujain/uatu/internal/trace" + "github.com/priyanshujain/sanderling/internal/trace" ) func newFixtureServer(t *testing.T) (*Server, string) { diff --git a/internal/runner/runner.go b/internal/runner/runner.go index d276db4..57903a3 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -8,12 +8,12 @@ import ( "log/slog" "time" - "github.com/priyanshujain/uatu/internal/agent" - "github.com/priyanshujain/uatu/internal/driver" - "github.com/priyanshujain/uatu/internal/hierarchy" - "github.com/priyanshujain/uatu/internal/ltl" - "github.com/priyanshujain/uatu/internal/trace" - "github.com/priyanshujain/uatu/internal/verifier" + "github.com/priyanshujain/sanderling/internal/agent" + "github.com/priyanshujain/sanderling/internal/driver" + "github.com/priyanshujain/sanderling/internal/hierarchy" + "github.com/priyanshujain/sanderling/internal/ltl" + "github.com/priyanshujain/sanderling/internal/trace" + "github.com/priyanshujain/sanderling/internal/verifier" ) type Options struct { diff --git a/internal/runner/runner_test.go b/internal/runner/runner_test.go index a7efb06..fb892da 100644 --- a/internal/runner/runner_test.go +++ b/internal/runner/runner_test.go @@ -15,19 +15,19 @@ import ( "testing" "time" - "github.com/priyanshujain/uatu/internal/agent" - mockdriver "github.com/priyanshujain/uatu/internal/driver/mock" - "github.com/priyanshujain/uatu/internal/trace" - "github.com/priyanshujain/uatu/internal/verifier" + "github.com/priyanshujain/sanderling/internal/agent" + mockdriver "github.com/priyanshujain/sanderling/internal/driver/mock" + "github.com/priyanshujain/sanderling/internal/trace" + "github.com/priyanshujain/sanderling/internal/verifier" ) const fixtureSpec = ` -const screen = __uatu__.extract(state => state.snapshots.screen ?? ""); -const balance = __uatu__.extract(state => state.snapshots.balance ?? 0); +const screen = __sanderling__.extract(state => state.snapshots.screen ?? ""); +const balance = __sanderling__.extract(state => state.snapshots.balance ?? 0); globalThis.properties = { - balanceNonNegative: __uatu__.always(() => balance.current >= 0), + balanceNonNegative: __sanderling__.always(() => balance.current >= 0), }; -globalThis.actions = __uatu__.actions(() => [__uatu__.tap({ on: "id:next" })]); +globalThis.actions = __sanderling__.actions(() => [__sanderling__.tap({ on: "id:next" })]); ` type harness struct { @@ -195,9 +195,9 @@ func TestRunner_ViolationSurfacesInSummary(t *testing.T) { func TestRunner_ThrowingPredicateIsLoggedNotPanic(t *testing.T) { const throwingSpec = ` globalThis.properties = { - broken: __uatu__.always(() => { throw new Error("bad predicate"); }), + broken: __sanderling__.always(() => { throw new Error("bad predicate"); }), }; -globalThis.actions = __uatu__.actions(() => [__uatu__.tap({ on: "id:next" })]); +globalThis.actions = __sanderling__.actions(() => [__sanderling__.tap({ on: "id:next" })]); ` state := newHarnessWithSpec(t, []map[string]json.RawMessage{{}, {}}, throwingSpec) state.startSDK(t) diff --git a/internal/sidecar/embed.go b/internal/sidecar/embed.go index e3f42ec..001a3a6 100644 --- a/internal/sidecar/embed.go +++ b/internal/sidecar/embed.go @@ -23,12 +23,12 @@ func EmbeddedSHA256() string { // matching checksum, no rewrite happens. Returns the JAR path. func Extract(dir string) (string, error) { if len(embeddedJAR) == 0 { - return "", errors.New("sidecar: binary built without -tags withsidecar; rebuild with `make uatu`") + return "", errors.New("sidecar: binary built without -tags withsidecar; rebuild with `make sanderling`") } if err := os.MkdirAll(dir, 0o755); err != nil { return "", fmt.Errorf("mkdir %s: %w", dir, err) } - jarPath := filepath.Join(dir, "uatu-sidecar.jar") + jarPath := filepath.Join(dir, "sanderling-sidecar.jar") checksumPath := jarPath + ".sha256" checksum := EmbeddedSHA256() diff --git a/internal/sidecar/embed_stub.go b/internal/sidecar/embed_stub.go index e9c707f..a2c9f9e 100644 --- a/internal/sidecar/embed_stub.go +++ b/internal/sidecar/embed_stub.go @@ -5,6 +5,6 @@ package sidecar var embeddedJAR []byte // IsPlaceholder reports whether the binary was built without the real -// sidecar JAR embedded. Build with `make uatu` (which passes +// sidecar JAR embedded. Build with `make sanderling` (which passes // -tags withsidecar) to embed the real fat JAR. func IsPlaceholder() bool { return true } diff --git a/internal/sidecar/embed_withsidecar_test.go b/internal/sidecar/embed_withsidecar_test.go index c7fc636..a2d1337 100644 --- a/internal/sidecar/embed_withsidecar_test.go +++ b/internal/sidecar/embed_withsidecar_test.go @@ -25,7 +25,7 @@ func TestExtract_WritesJARAndChecksum(t *testing.T) { if err != nil { t.Fatal(err) } - if path != filepath.Join(directory, "uatu-sidecar.jar") { + if path != filepath.Join(directory, "sanderling-sidecar.jar") { t.Errorf("unexpected path: %s", path) } body, err := os.ReadFile(path) diff --git a/internal/trace/writer.go b/internal/trace/writer.go index 26b7b46..4dfad4a 100644 --- a/internal/trace/writer.go +++ b/internal/trace/writer.go @@ -9,7 +9,7 @@ import ( "sync" "time" - "github.com/priyanshujain/uatu/internal/hierarchy" + "github.com/priyanshujain/sanderling/internal/hierarchy" ) type Step struct { @@ -74,7 +74,7 @@ type Meta struct { BundleID string `json:"bundle_id"` StartedAt time.Time `json:"started_at"` EndedAt *time.Time `json:"ended_at,omitempty"` - UatuVersion string `json:"uatu_version"` + SanderlingVersion string `json:"sanderling_version"` } type Writer struct { diff --git a/internal/trace/writer_test.go b/internal/trace/writer_test.go index d18a25f..454656c 100644 --- a/internal/trace/writer_test.go +++ b/internal/trace/writer_test.go @@ -25,7 +25,7 @@ func TestWriteMeta_RoundTrip(t *testing.T) { Platform: "android", BundleID: "in.okcredit.merchant", StartedAt: time.Date(2026, 4, 17, 22, 30, 0, 0, time.UTC), - UatuVersion: "0.0.1", + SanderlingVersion: "0.0.1", } if err := writer.WriteMeta(meta); err != nil { t.Fatal(err) @@ -60,7 +60,7 @@ func TestWriteMeta_EndedAtRoundTrip(t *testing.T) { BundleID: "in.test", StartedAt: time.Date(2026, 4, 17, 22, 30, 0, 0, time.UTC), EndedAt: &endedAt, - UatuVersion: "0.0.1", + SanderlingVersion: "0.0.1", } if err := writer.WriteMeta(meta); err != nil { t.Fatal(err) diff --git a/internal/verifier/ax_integration_test.go b/internal/verifier/ax_integration_test.go index be1277f..9ff5aeb 100644 --- a/internal/verifier/ax_integration_test.go +++ b/internal/verifier/ax_integration_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/priyanshujain/uatu/internal/hierarchy" + "github.com/priyanshujain/sanderling/internal/hierarchy" ) // TestStateAxFindWorks verifies that a Parse+PushSnapshot+extract round trip @@ -24,11 +24,11 @@ func TestStateAxFindWorks(t *testing.T) { verifier := newVerifier(t) mustLoad(t, verifier, ` - globalThis.probe = __uatu__.extract(state => { + globalThis.probe = __sanderling__.extract(state => { const element = state.ax.find("id:select_language"); return element ? "matched:" + element.text : "miss"; }); - globalThis.count = __uatu__.extract(state => state.ax.findAll("id:select_language").length); + globalThis.count = __sanderling__.extract(state => state.ax.findAll("id:select_language").length); `) if err := verifier.PushSnapshot(SnapshotInput{Snapshots: Snapshots{}, Tree: tree}); err != nil { diff --git a/internal/verifier/bindings.go b/internal/verifier/bindings.go index 20fca55..4703136 100644 --- a/internal/verifier/bindings.go +++ b/internal/verifier/bindings.go @@ -80,11 +80,11 @@ type formulaSpec struct { } const ( - tagFormula = "__uatuFormula" - tagFormulaSpecIndex = "__uatuFormulaSpec" - tagActionGenerator = "__uatuActionGenerator" - tagInternalKind = "__uatuKind" - tagSelector = "__uatuSelector" + tagFormula = "__sanderlingFormula" + tagFormulaSpecIndex = "__sanderlingFormulaSpec" + tagActionGenerator = "__sanderlingActionGenerator" + tagInternalKind = "__sanderlingKind" + tagSelector = "__sanderlingSelector" internalKindActions = "actions" internalKindWeighted = "weighted" @@ -94,63 +94,63 @@ const ( internalKindBuiltinPressKey = "pressKey" ) -// installRuntimeBindings exposes globalThis.__uatu__ to the loaded spec. +// installRuntimeBindings exposes globalThis.__sanderling__ to the loaded spec. func (v *Verifier) installRuntimeBindings() error { - uatu := v.runtime.NewObject() + sanderling := v.runtime.NewObject() - if err := uatu.Set("extract", v.bindExtract); err != nil { + if err := sanderling.Set("extract", v.bindExtract); err != nil { return err } - if err := uatu.Set("always", v.bindAlways); err != nil { + if err := sanderling.Set("always", v.bindAlways); err != nil { return err } - if err := uatu.Set("now", v.bindNow); err != nil { + if err := sanderling.Set("now", v.bindNow); err != nil { return err } - if err := uatu.Set("next", v.bindNext); err != nil { + if err := sanderling.Set("next", v.bindNext); err != nil { return err } - if err := uatu.Set("eventually", v.bindEventually); err != nil { + if err := sanderling.Set("eventually", v.bindEventually); err != nil { return err } - if err := uatu.Set("actions", v.bindActions); err != nil { + if err := sanderling.Set("actions", v.bindActions); err != nil { return err } - if err := uatu.Set("weighted", v.bindWeighted); err != nil { + if err := sanderling.Set("weighted", v.bindWeighted); err != nil { return err } - if err := uatu.Set("from", v.bindFrom); err != nil { + if err := sanderling.Set("from", v.bindFrom); err != nil { return err } - if err := uatu.Set("tap", v.bindTap); err != nil { + if err := sanderling.Set("tap", v.bindTap); err != nil { return err } - if err := uatu.Set("inputText", v.bindInputText); err != nil { + if err := sanderling.Set("inputText", v.bindInputText); err != nil { return err } - if err := uatu.Set("swipe", v.bindSwipe); err != nil { + if err := sanderling.Set("swipe", v.bindSwipe); err != nil { return err } - if err := uatu.Set("pressKey", v.bindPressKey); err != nil { + if err := sanderling.Set("pressKey", v.bindPressKey); err != nil { return err } - if err := uatu.Set("wait", v.bindWait); err != nil { + if err := sanderling.Set("wait", v.bindWait); err != nil { return err } - if err := uatu.Set("taps", v.builtinGenerator(internalKindBuiltinTaps)); err != nil { + if err := sanderling.Set("taps", v.builtinGenerator(internalKindBuiltinTaps)); err != nil { return err } - if err := uatu.Set("swipes", v.builtinGenerator(internalKindBuiltinSwipes)); err != nil { + if err := sanderling.Set("swipes", v.builtinGenerator(internalKindBuiltinSwipes)); err != nil { return err } - if err := uatu.Set("waitOnce", v.builtinGenerator(internalKindBuiltinWaitOnce)); err != nil { + if err := sanderling.Set("waitOnce", v.builtinGenerator(internalKindBuiltinWaitOnce)); err != nil { return err } - if err := uatu.Set("pressKeys", v.builtinGenerator(internalKindBuiltinPressKey)); err != nil { + if err := sanderling.Set("pressKeys", v.builtinGenerator(internalKindBuiltinPressKey)); err != nil { return err } - return v.runtime.GlobalObject().Set("__uatu__", uatu) + return v.runtime.GlobalObject().Set("__sanderling__", sanderling) } func (v *Verifier) bindExtract(call goja.FunctionCall) goja.Value { @@ -172,7 +172,7 @@ func (v *Verifier) bindExtract(call goja.FunctionCall) goja.Value { // bindAlways accepts either a predicate function (legacy shape) or a formula // handle (new shape). Both produce a formula handle tagged with -// __uatuFormulaSpec. +// __sanderlingFormulaSpec. func (v *Verifier) bindAlways(call goja.FunctionCall) goja.Value { if len(call.Arguments) != 1 { panic(v.runtime.NewTypeError("always requires exactly one argument")) @@ -258,9 +258,9 @@ func (v *Verifier) formulaHandle(kind specKind, index int) *goja.Object { handle := v.runtime.NewObject() _ = handle.Set(tagFormula, true) _ = handle.Set(tagFormulaSpecIndex, index) - // Keep __uatuIndex as an alias so older property shapes that read it keep + // Keep __sanderlingIndex as an alias so older property shapes that read it keep // working during backward-compat transitions. - _ = handle.Set("__uatuIndex", index) + _ = handle.Set("__sanderlingIndex", index) _ = handle.Set("implies", v.binaryChain(index, specKindImplies)) _ = handle.Set("or", v.binaryChain(index, specKindOr)) @@ -326,7 +326,7 @@ func (v *Verifier) eventuallyWithin(selfIndex int) func(call goja.FunctionCall) } } -// extractSpecIndex reads __uatuFormulaSpec from a JS formula handle. +// extractSpecIndex reads __sanderlingFormulaSpec from a JS formula handle. func (v *Verifier) extractSpecIndex(value goja.Value) (int, bool) { if value == nil || goja.IsNull(value) || goja.IsUndefined(value) { return 0, false diff --git a/internal/verifier/marshal.go b/internal/verifier/marshal.go index 130fd3c..780270d 100644 --- a/internal/verifier/marshal.go +++ b/internal/verifier/marshal.go @@ -7,7 +7,7 @@ import ( "github.com/dop251/goja" - "github.com/priyanshujain/uatu/internal/hierarchy" + "github.com/priyanshujain/sanderling/internal/hierarchy" ) // Snapshots is the per-step extractor output forwarded by the SDK. diff --git a/internal/verifier/spec_integration_test.go b/internal/verifier/spec_integration_test.go index 5b0e077..6c448c2 100644 --- a/internal/verifier/spec_integration_test.go +++ b/internal/verifier/spec_integration_test.go @@ -5,13 +5,13 @@ import ( "path/filepath" "testing" - "github.com/priyanshujain/uatu/internal/bundler" - "github.com/priyanshujain/uatu/internal/hierarchy" - "github.com/priyanshujain/uatu/internal/ltl" + "github.com/priyanshujain/sanderling/internal/bundler" + "github.com/priyanshujain/sanderling/internal/hierarchy" + "github.com/priyanshujain/sanderling/internal/ltl" ) // bundleIntegrationSpec bundles testdata/integration_spec.ts via the real -// @uatu/spec API so the integration test exercises the same path the CLI +// @sanderling/spec API so the integration test exercises the same path the CLI // uses, with no reference to any specific example app. func bundleIntegrationSpec(t *testing.T) string { t.Helper() @@ -30,8 +30,8 @@ func bundleIntegrationSpec(t *testing.T) string { bundle, err := bundler.Bundle(bundler.Options{ EntryFile: specPath, Aliases: map[string]string{ - "@uatu/spec": apiPath, - "@uatu/spec/defaults/properties": defaultsPath, + "@sanderling/spec": apiPath, + "@sanderling/spec/defaults/properties": defaultsPath, }, }) if err != nil { diff --git a/internal/verifier/testdata/integration_spec.ts b/internal/verifier/testdata/integration_spec.ts index 5ad2a16..ba32ef2 100644 --- a/internal/verifier/testdata/integration_spec.ts +++ b/internal/verifier/testdata/integration_spec.ts @@ -6,8 +6,8 @@ import { eventually, extract, weighted, -} from "@uatu/spec"; -import { noUncaughtExceptions } from "@uatu/spec/defaults/properties"; +} from "@sanderling/spec"; +import { noUncaughtExceptions } from "@sanderling/spec/defaults/properties"; const route = extract( (state) => (state.snapshots.route as string) ?? "", diff --git a/internal/verifier/verifier_test.go b/internal/verifier/verifier_test.go index 8c58f33..f86986c 100644 --- a/internal/verifier/verifier_test.go +++ b/internal/verifier/verifier_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/priyanshujain/uatu/internal/ltl" + "github.com/priyanshujain/sanderling/internal/ltl" ) func newVerifier(t *testing.T, options ...Option) *Verifier { @@ -27,18 +27,18 @@ func mustLoad(t *testing.T, verifier *Verifier, source string) { } const helloSpec = ` -const screen = __uatu__.extract(state => state.snapshots.screen ?? ""); -const balance = __uatu__.extract(state => state.snapshots["ledger.balance"] ?? 0); +const screen = __sanderling__.extract(state => state.snapshots.screen ?? ""); +const balance = __sanderling__.extract(state => state.snapshots["ledger.balance"] ?? 0); globalThis.screen = screen; globalThis.balance = balance; globalThis.properties = { - balanceNonNegative: __uatu__.always(() => balance.current >= 0), + balanceNonNegative: __sanderling__.always(() => balance.current >= 0), }; -globalThis.actions = __uatu__.actions(() => [ - __uatu__.tap({ on: "id:home_button" }), +globalThis.actions = __sanderling__.actions(() => [ + __sanderling__.tap({ on: "id:home_button" }), ]); ` @@ -135,9 +135,9 @@ func TestNextAction_FromActionsGenerator(t *testing.T) { func TestNextAction_WeightedSelectsByWeight(t *testing.T) { verifier := newVerifier(t, WithRand(rand.New(rand.NewPCG(42, 0)))) mustLoad(t, verifier, ` - const tapHome = __uatu__.actions(() => [__uatu__.tap({ on: "id:home" })]); - const tapAway = __uatu__.actions(() => [__uatu__.tap({ on: "id:away" })]); - globalThis.actions = __uatu__.weighted( + const tapHome = __sanderling__.actions(() => [__sanderling__.tap({ on: "id:home" })]); + const tapAway = __sanderling__.actions(() => [__sanderling__.tap({ on: "id:away" })]); + globalThis.actions = __sanderling__.weighted( [1, tapHome], [99, tapAway], ); @@ -166,7 +166,7 @@ func TestNextAction_WeightedSelectsByWeight(t *testing.T) { func TestNextAction_EmptyGeneratorReturnsErrNoAction(t *testing.T) { verifier := newVerifier(t) mustLoad(t, verifier, ` - globalThis.actions = __uatu__.actions(() => []); + globalThis.actions = __sanderling__.actions(() => []); `) _ = verifier.PushSnapshot(SnapshotInput{Snapshots: Snapshots{}}) @@ -179,8 +179,8 @@ func TestNextAction_EmptyGeneratorReturnsErrNoAction(t *testing.T) { func TestInputText_RoundTrip(t *testing.T) { verifier := newVerifier(t) mustLoad(t, verifier, ` - globalThis.actions = __uatu__.actions(() => [ - __uatu__.inputText({ into: "id:phone", text: "+919876543210" }), + globalThis.actions = __sanderling__.actions(() => [ + __sanderling__.inputText({ into: "id:phone", text: "+919876543210" }), ]); `) _ = verifier.PushSnapshot(SnapshotInput{Snapshots: Snapshots{}}) @@ -200,7 +200,7 @@ func TestInputText_RoundTrip(t *testing.T) { func TestPushSnapshot_FeedsSnapshotsToExtractorState(t *testing.T) { verifier := newVerifier(t) mustLoad(t, verifier, ` - globalThis.captured = __uatu__.extract(state => state.snapshots["k"]); + globalThis.captured = __sanderling__.extract(state => state.snapshots["k"]); `) if err := verifier.PushSnapshot(SnapshotInput{Snapshots: Snapshots{"k": json.RawMessage(`"hello"`)}}); err != nil { t.Fatal(err) @@ -222,7 +222,7 @@ func TestLoad_PropagatesSyntaxError(t *testing.T) { func TestEvaluateProperties_ThrowingPredicateDoesNotPanic(t *testing.T) { const spec = ` globalThis.properties = { - broken: __uatu__.always(() => { throw new Error("bad predicate"); }), + broken: __sanderling__.always(() => { throw new Error("bad predicate"); }), }; ` verifier := newVerifier(t) diff --git a/internal/verifier/worker.go b/internal/verifier/worker.go index 6fdd389..00e698d 100644 --- a/internal/verifier/worker.go +++ b/internal/verifier/worker.go @@ -8,8 +8,8 @@ import ( "github.com/dop251/goja" - "github.com/priyanshujain/uatu/internal/hierarchy" - "github.com/priyanshujain/uatu/internal/ltl" + "github.com/priyanshujain/sanderling/internal/hierarchy" + "github.com/priyanshujain/sanderling/internal/ltl" ) type Verifier struct { diff --git a/pkg/spec-api/README.md b/pkg/spec-api/README.md index 87ed45d..df033d3 100644 --- a/pkg/spec-api/README.md +++ b/pkg/spec-api/README.md @@ -1,19 +1,19 @@ -# @uatu/spec +# @sanderling/spec -TypeScript spec API for [uatu](https://github.com/priyanshujain/uatu), a property-based UI fuzzer for mobile apps. +TypeScript spec API for [sanderling](https://github.com/priyanshujain/sanderling), a property-based UI fuzzer for mobile apps. -Spec authors write specs in TypeScript that describe what an app should *always* do (safety invariants), generate weighted actions to exercise the app, and extract structured state from the accessibility tree. The `uatu` CLI picks up the spec and drives the app under test. +Spec authors write specs in TypeScript that describe what an app should *always* do (safety invariants), generate weighted actions to exercise the app, and extract structured state from the accessibility tree. The `sanderling` CLI picks up the spec and drives the app under test. ## Install ```sh -npm install --save-dev @uatu/spec +npm install --save-dev @sanderling/spec ``` ## Usage ```ts -import { extract, always, actions, Tap, weighted } from "@uatu/spec"; +import { extract, always, actions, Tap, weighted } from "@sanderling/spec"; export const spec = { extract: extract((tree) => ({ @@ -32,7 +32,7 @@ export const spec = { ## Version compatibility -`@uatu/spec` is released in lockstep with the uatu CLI. Pin the same major/minor version as your installed `uatu` binary. +`@sanderling/spec` is released in lockstep with the sanderling CLI. Pin the same major/minor version as your installed `sanderling` binary. ## License diff --git a/pkg/spec-api/package-lock.json b/pkg/spec-api/package-lock.json index 2597f10..31fb500 100644 --- a/pkg/spec-api/package-lock.json +++ b/pkg/spec-api/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@uatu/spec", + "name": "@sanderling/spec", "version": "0.0.0-dev", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@uatu/spec", + "name": "@sanderling/spec", "version": "0.0.0-dev", "license": "Apache-2.0", "devDependencies": { diff --git a/pkg/spec-api/package.json b/pkg/spec-api/package.json index ca8a738..9bbda01 100644 --- a/pkg/spec-api/package.json +++ b/pkg/spec-api/package.json @@ -1,7 +1,7 @@ { - "name": "@uatu/spec", + "name": "@sanderling/spec", "version": "0.0.0-dev", - "description": "TypeScript spec API for uatu, a property-based UI fuzzer for mobile apps.", + "description": "TypeScript spec API for sanderling, a property-based UI fuzzer for mobile apps.", "type": "module", "types": "./dist/index.d.ts", "main": "./dist/index.js", @@ -21,12 +21,12 @@ ], "repository": { "type": "git", - "url": "git+https://github.com/priyanshujain/uatu.git", + "url": "git+https://github.com/priyanshujain/sanderling.git", "directory": "pkg/spec-api" }, - "homepage": "https://github.com/priyanshujain/uatu", + "homepage": "https://github.com/priyanshujain/sanderling", "bugs": { - "url": "https://github.com/priyanshujain/uatu/issues" + "url": "https://github.com/priyanshujain/sanderling/issues" }, "license": "Apache-2.0", "author": "Priyanshu Jain", diff --git a/pkg/spec-api/src/actions.ts b/pkg/spec-api/src/actions.ts index 370ebe4..9e2f160 100644 --- a/pkg/spec-api/src/actions.ts +++ b/pkg/spec-api/src/actions.ts @@ -14,26 +14,26 @@ import type { } from "./types.ts"; export function actions(generator: () => Action[]): ActionGenerator { - return globalThis.__uatu__.actions(generator); + return globalThis.__sanderling__.actions(generator); } export function weighted(...entries: WeightedEntry[]): ActionGenerator { - return globalThis.__uatu__.weighted(...entries); + return globalThis.__sanderling__.weighted(...entries); } export function from(items: readonly T[]): Sampler { - return globalThis.__uatu__.from(items); + return globalThis.__sanderling__.from(items); } export function Tap(parameters: { on: string | AccessibilityElement }): TapAction { - return globalThis.__uatu__.tap(parameters); + return globalThis.__sanderling__.tap(parameters); } export function InputText(parameters: { into: string | AccessibilityElement; text: string; }): InputTextAction { - return globalThis.__uatu__.inputText(parameters); + return globalThis.__sanderling__.inputText(parameters); } export function Swipe(parameters: { @@ -41,21 +41,21 @@ export function Swipe(parameters: { to: Point | AccessibilityElement; durationMillis?: number; }): SwipeAction { - return globalThis.__uatu__.swipe(parameters); + return globalThis.__sanderling__.swipe(parameters); } export function PressKey(parameters: { key: Key }): PressKeyAction { - return globalThis.__uatu__.pressKey(parameters); + return globalThis.__sanderling__.pressKey(parameters); } export function Wait(parameters: { durationMillis: number }): WaitAction { - return globalThis.__uatu__.wait(parameters); + return globalThis.__sanderling__.wait(parameters); } function builtinGenerator(name: "taps" | "swipes" | "waitOnce" | "pressKeys"): ActionGenerator { return new Proxy({} as ActionGenerator, { get(_target, property) { - const runtime = globalThis.__uatu__[name] as unknown as Record< + const runtime = globalThis.__sanderling__[name] as unknown as Record< string | symbol, unknown >; diff --git a/pkg/spec-api/src/defaults/properties.ts b/pkg/spec-api/src/defaults/properties.ts index 38bc765..6fecbbb 100644 --- a/pkg/spec-api/src/defaults/properties.ts +++ b/pkg/spec-api/src/defaults/properties.ts @@ -4,7 +4,7 @@ import type { Formula } from "../types.ts"; const exceptionCount = extract((state) => state.exceptions.length); -// Fails when the SDK captured an uncaught throwable or a Uatu.reportError +// Fails when the SDK captured an uncaught throwable or a Sanderling.reportError // call surfaced one during the run. export const noUncaughtExceptions: Formula = always( () => exceptionCount.current === 0, diff --git a/pkg/spec-api/src/extract.ts b/pkg/spec-api/src/extract.ts index a0181d7..320e6e2 100644 --- a/pkg/spec-api/src/extract.ts +++ b/pkg/spec-api/src/extract.ts @@ -1,5 +1,5 @@ import type { Extracted, State } from "./types.ts"; export function extract(getter: (state: State) => T): Extracted { - return globalThis.__uatu__.extract(getter); + return globalThis.__sanderling__.extract(getter); } diff --git a/pkg/spec-api/src/index.ts b/pkg/spec-api/src/index.ts index 0c5822e..f046b41 100644 --- a/pkg/spec-api/src/index.ts +++ b/pkg/spec-api/src/index.ts @@ -17,7 +17,7 @@ export type { State, SwipeAction, TapAction, - UatuRuntime, + SanderlingRuntime, WaitAction, WeightedEntry, } from "./types.ts"; diff --git a/pkg/spec-api/src/ltl.ts b/pkg/spec-api/src/ltl.ts index 5516cc5..e0fff27 100644 --- a/pkg/spec-api/src/ltl.ts +++ b/pkg/spec-api/src/ltl.ts @@ -1,20 +1,20 @@ import type { EventuallyFormula, Formula } from "./types.ts"; export function always(predicateOrFormula: (() => boolean) | Formula): Formula { - return globalThis.__uatu__.always(predicateOrFormula); + return globalThis.__sanderling__.always(predicateOrFormula); } export function now(predicate: () => boolean): Formula { - return globalThis.__uatu__.now(predicate); + return globalThis.__sanderling__.now(predicate); } export function next(predicate: () => boolean): Formula { - return globalThis.__uatu__.next(predicate); + return globalThis.__sanderling__.next(predicate); } // An unbounded `eventually` never forces a violation within a finite run — // prefer `.within(n, unit)` when you want the verifier to fail a property // that stalls. export function eventually(predicate: () => boolean): EventuallyFormula { - return globalThis.__uatu__.eventually(predicate); + return globalThis.__sanderling__.eventually(predicate); } diff --git a/pkg/spec-api/src/types.ts b/pkg/spec-api/src/types.ts index c83c3d6..a33a612 100644 --- a/pkg/spec-api/src/types.ts +++ b/pkg/spec-api/src/types.ts @@ -78,12 +78,12 @@ export type Key = | "right"; export interface ActionGenerator { - readonly __uatuActionGenerator: true; + readonly __sanderlingActionGenerator: true; generate(): Action[]; } export interface Formula { - readonly __uatuFormula: true; + readonly __sanderlingFormula: true; implies(other: Formula): Formula; or(other: Formula): Formula; and(other: Formula): Formula; @@ -98,7 +98,7 @@ export interface Sampler { generate(): T; } -export interface UatuRuntime { +export interface SanderlingRuntime { extract: (getter: (state: State) => T) => Extracted; always: (predicateOrFormula: (() => boolean) | Formula) => Formula; now: (predicate: () => boolean) => Formula; @@ -129,5 +129,5 @@ export type WeightedEntry = readonly [number, ActionGenerator]; declare global { // eslint-disable-next-line no-var - var __uatu__: UatuRuntime; + var __sanderling__: SanderlingRuntime; } diff --git a/pkg/spec-api/test/api.test.ts b/pkg/spec-api/test/api.test.ts index edde412..891db82 100644 --- a/pkg/spec-api/test/api.test.ts +++ b/pkg/spec-api/test/api.test.ts @@ -29,11 +29,11 @@ import type { Formula, Sampler, State, - UatuRuntime, + SanderlingRuntime, WeightedEntry, } from "../src/types.ts"; -interface RecordedRuntime extends UatuRuntime { +interface RecordedRuntime extends SanderlingRuntime { extracts: Array<(state: State) => unknown>; alwaysArgs: Array<(() => boolean) | Formula>; nowPredicates: Array<() => boolean>; @@ -51,7 +51,7 @@ interface RecordedRuntime extends UatuRuntime { function makeChainableFormula(record: RecordedRuntime): Formula { const formula: Formula = { - __uatuFormula: true, + __sanderlingFormula: true, implies(other: Formula): Formula { record.impliesCalls++; void other; @@ -125,11 +125,11 @@ function installFakeRuntime(): RecordedRuntime { }, actions: (generator: () => Action[]): ActionGenerator => { calls.actionGenerators.push(generator); - return { __uatuActionGenerator: true, generate: generator }; + return { __sanderlingActionGenerator: true, generate: generator }; }, weighted: (...entries: WeightedEntry[]): ActionGenerator => { calls.weightedCalls.push(entries); - return { __uatuActionGenerator: true, generate: () => [] }; + return { __sanderlingActionGenerator: true, generate: () => [] }; }, from: (items: readonly T[]): Sampler => { calls.fromCalls.push(items as unknown[]); @@ -145,13 +145,13 @@ function installFakeRuntime(): RecordedRuntime { }), pressKey: ({ key }) => ({ kind: "PressKey", key }), wait: ({ durationMillis }) => ({ kind: "Wait", durationMillis }), - taps: { __uatuActionGenerator: true, generate: () => [] }, - swipes: { __uatuActionGenerator: true, generate: () => [] }, - waitOnce: { __uatuActionGenerator: true, generate: () => [] }, - pressKeys: { __uatuActionGenerator: true, generate: () => [] }, - } satisfies UatuRuntime; + taps: { __sanderlingActionGenerator: true, generate: () => [] }, + swipes: { __sanderlingActionGenerator: true, generate: () => [] }, + waitOnce: { __sanderlingActionGenerator: true, generate: () => [] }, + pressKeys: { __sanderlingActionGenerator: true, generate: () => [] }, + } satisfies SanderlingRuntime; const recorded = Object.assign(runtime, calls) as RecordedRuntime; - globalThis.__uatu__ = recorded; + globalThis.__sanderling__ = recorded; return recorded; } @@ -168,7 +168,7 @@ test("always wraps a predicate into a formula via the runtime", () => { const predicate = () => true; const formula = always(predicate); assert.equal(runtime.alwaysArgs[0], predicate); - assert.equal(formula.__uatuFormula, true); + assert.equal(formula.__sanderlingFormula, true); }); test("always accepts a formula handle", () => { @@ -176,7 +176,7 @@ test("always accepts a formula handle", () => { const inner = now(() => true); const wrapped = always(inner); assert.equal(runtime.alwaysArgs.at(-1), inner); - assert.equal(wrapped.__uatuFormula, true); + assert.equal(wrapped.__sanderlingFormula, true); }); test("now/next/eventually forward predicates", () => { @@ -257,7 +257,7 @@ test("actions wraps a generator into the runtime's ActionGenerator", () => { const generator = () => [Tap({ on: "id:x" })]; const wrapped = actions(generator); assert.equal(runtime.actionGenerators[0], generator); - assert.equal(wrapped.__uatuActionGenerator, true); + assert.equal(wrapped.__sanderlingActionGenerator, true); }); test("weighted forwards weighted entries to the runtime", () => { @@ -279,8 +279,8 @@ test("from forwards items to the runtime", () => { test("default generators proxy through to the runtime", () => { installFakeRuntime(); - assert.equal(taps.__uatuActionGenerator, true); - assert.equal(swipes.__uatuActionGenerator, true); - assert.equal(waitOnce.__uatuActionGenerator, true); - assert.equal(pressKey.__uatuActionGenerator, true); + assert.equal(taps.__sanderlingActionGenerator, true); + assert.equal(swipes.__sanderlingActionGenerator, true); + assert.equal(waitOnce.__sanderlingActionGenerator, true); + assert.equal(pressKey.__sanderlingActionGenerator, true); }); diff --git a/pkg/spec-api/test/defaults.test.ts b/pkg/spec-api/test/defaults.test.ts index 5222a42..4fcb6e2 100644 --- a/pkg/spec-api/test/defaults.test.ts +++ b/pkg/spec-api/test/defaults.test.ts @@ -9,11 +9,11 @@ import type { Formula, Sampler, State, - UatuRuntime, + SanderlingRuntime, WeightedEntry, } from "../src/types.ts"; -interface RecordedRuntime extends UatuRuntime { +interface RecordedRuntime extends SanderlingRuntime { currentState: State; extractors: Array<(state: State) => unknown>; alwaysArgs: Array<(() => boolean) | Formula>; @@ -43,17 +43,17 @@ function installRuntime(initialState: State): RecordedRuntime { if (typeof predicateOrFormula === "function") { lastPredicate = predicateOrFormula; } - return { __uatuFormula: true } as Formula; + return { __sanderlingFormula: true } as Formula; }, - now: () => ({ __uatuFormula: true } as Formula), - next: () => ({ __uatuFormula: true } as Formula), - eventually: () => ({ __uatuFormula: true } as EventuallyFormula), + now: () => ({ __sanderlingFormula: true } as Formula), + next: () => ({ __sanderlingFormula: true } as Formula), + eventually: () => ({ __sanderlingFormula: true } as EventuallyFormula), actions: (generator: () => Action[]): ActionGenerator => ({ - __uatuActionGenerator: true, + __sanderlingActionGenerator: true, generate: generator, }), weighted: (..._entries: WeightedEntry[]): ActionGenerator => ({ - __uatuActionGenerator: true, + __sanderlingActionGenerator: true, generate: () => [], }), from: (_items: readonly T[]): Sampler => ({ generate: () => _items[0] as T }), @@ -62,11 +62,11 @@ function installRuntime(initialState: State): RecordedRuntime { swipe: (p) => ({ kind: "Swipe", from: p.from, to: p.to, durationMillis: p.durationMillis }), pressKey: ({ key }) => ({ kind: "PressKey", key }), wait: ({ durationMillis }) => ({ kind: "Wait", durationMillis }), - taps: { __uatuActionGenerator: true, generate: () => [] } as ActionGenerator, - swipes: { __uatuActionGenerator: true, generate: () => [] } as ActionGenerator, - waitOnce: { __uatuActionGenerator: true, generate: () => [] } as ActionGenerator, - pressKeys: { __uatuActionGenerator: true, generate: () => [] } as ActionGenerator, - } satisfies UatuRuntime; + taps: { __sanderlingActionGenerator: true, generate: () => [] } as ActionGenerator, + swipes: { __sanderlingActionGenerator: true, generate: () => [] } as ActionGenerator, + waitOnce: { __sanderlingActionGenerator: true, generate: () => [] } as ActionGenerator, + pressKeys: { __sanderlingActionGenerator: true, generate: () => [] } as ActionGenerator, + } satisfies SanderlingRuntime; const state = { currentState: initialState }; const recorded = Object.assign(runtime, { @@ -77,7 +77,7 @@ function installRuntime(initialState: State): RecordedRuntime { return lastPredicate; }, }) as unknown as RecordedRuntime; - globalThis.__uatu__ = recorded; + globalThis.__sanderling__ = recorded; // Re-bind state ref so subsequent extract() calls read the up-to-date state. Object.defineProperty(recorded, "currentState", { get() { @@ -105,6 +105,6 @@ test("defaults bundle exports formulas tagged as LTL properties", async () => { logs: [{ unixMillis: 1, level: "W", tag: "X", message: "warn" }], }); const defaults = await import("../src/defaults/properties.ts"); - assert.equal(defaults.noUncaughtExceptions.__uatuFormula, true); - assert.equal(defaults.noLogcatErrors.__uatuFormula, true); + assert.equal(defaults.noUncaughtExceptions.__sanderlingFormula, true); + assert.equal(defaults.noLogcatErrors.__sanderlingFormula, true); }); diff --git a/proto/driverpb/driver.pb.go b/proto/driverpb/driver.pb.go index 445cf7e..8b7e0c5 100644 --- a/proto/driverpb/driver.pb.go +++ b/proto/driverpb/driver.pb.go @@ -849,7 +849,7 @@ var File_driverpb_driver_proto protoreflect.FileDescriptor const file_driverpb_driver_proto_rawDesc = "" + "\n" + - "\x15driverpb/driver.proto\x12\x0euatu.driver.v1\"\a\n" + + "\x15driverpb/driver.proto\x12\x14sanderling.driver.v1\"\a\n" + "\x05Empty\"z\n" + "\rLaunchRequest\x12\x1b\n" + "\tbundle_id\x18\x01 \x01(\tR\bbundleId\x12\x1f\n" + @@ -874,19 +874,19 @@ const file_driverpb_driver_proto_rawDesc = "" + "\fHealthStatus\x12\x14\n" + "\x05ready\x18\x01 \x01(\bR\x05ready\x12\x18\n" + "\aversion\x18\x02 \x01(\tR\aversion\x12\x1a\n" + - "\bplatform\x18\x03 \x01(\tR\bplatform\"\x89\x01\n" + - "\fSwipeRequest\x12)\n" + - "\x04from\x18\x01 \x01(\v2\x15.uatu.driver.v1.PointR\x04from\x12%\n" + - "\x02to\x18\x02 \x01(\v2\x15.uatu.driver.v1.PointR\x02to\x12'\n" + + "\bplatform\x18\x03 \x01(\tR\bplatform\"\x95\x01\n" + + "\fSwipeRequest\x12/\n" + + "\x04from\x18\x01 \x01(\v2\x1b.sanderling.driver.v1.PointR\x04from\x12+\n" + + "\x02to\x18\x02 \x01(\v2\x1b.sanderling.driver.v1.PointR\x02to\x12'\n" + "\x0fduration_millis\x18\x03 \x01(\x03R\x0edurationMillis\"#\n" + "\x0fPressKeyRequest\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\"e\n" + "\x11RecentLogsRequest\x12*\n" + "\x11since_unix_millis\x18\x01 \x01(\x03R\x0fsinceUnixMillis\x12$\n" + - "\x0elevel_at_least\x18\x02 \x01(\tR\flevelAtLeast\"@\n" + + "\x0elevel_at_least\x18\x02 \x01(\tR\flevelAtLeast\"F\n" + "\n" + - "LogEntries\x122\n" + - "\aentries\x18\x01 \x03(\v2\x18.uatu.driver.v1.LogEntryR\aentries\"m\n" + + "LogEntries\x128\n" + + "\aentries\x18\x01 \x03(\v2\x1e.sanderling.driver.v1.LogEntryR\aentries\"m\n" + "\bLogEntry\x12\x1f\n" + "\vunix_millis\x18\x01 \x01(\x03R\n" + "unixMillis\x12\x14\n" + @@ -900,24 +900,24 @@ const file_driverpb_driver_proto_rawDesc = "" + "cpuPercent\x12\x1d\n" + "\n" + "heap_bytes\x18\x02 \x01(\x03R\theapBytes\x12,\n" + - "\x12total_memory_bytes\x18\x03 \x01(\x03R\x10totalMemoryBytes2\xcb\x06\n" + - "\x06Driver\x12>\n" + - "\x06Launch\x12\x1d.uatu.driver.v1.LaunchRequest\x1a\x15.uatu.driver.v1.Empty\x129\n" + - "\tTerminate\x12\x15.uatu.driver.v1.Empty\x1a\x15.uatu.driver.v1.Empty\x123\n" + - "\x03Tap\x12\x15.uatu.driver.v1.Point\x1a\x15.uatu.driver.v1.Empty\x12>\n" + - "\vTapSelector\x12\x18.uatu.driver.v1.Selector\x1a\x15.uatu.driver.v1.Empty\x128\n" + - "\tInputText\x12\x14.uatu.driver.v1.Text\x1a\x15.uatu.driver.v1.Empty\x12<\n" + - "\x05Swipe\x12\x1c.uatu.driver.v1.SwipeRequest\x1a\x15.uatu.driver.v1.Empty\x12B\n" + - "\bPressKey\x12\x1f.uatu.driver.v1.PressKeyRequest\x1a\x15.uatu.driver.v1.Empty\x12:\n" + + "\x12total_memory_bytes\x18\x03 \x01(\x03R\x10totalMemoryBytes2\xe7\a\n" + + "\x06Driver\x12J\n" + + "\x06Launch\x12#.sanderling.driver.v1.LaunchRequest\x1a\x1b.sanderling.driver.v1.Empty\x12E\n" + + "\tTerminate\x12\x1b.sanderling.driver.v1.Empty\x1a\x1b.sanderling.driver.v1.Empty\x12?\n" + + "\x03Tap\x12\x1b.sanderling.driver.v1.Point\x1a\x1b.sanderling.driver.v1.Empty\x12J\n" + + "\vTapSelector\x12\x1e.sanderling.driver.v1.Selector\x1a\x1b.sanderling.driver.v1.Empty\x12D\n" + + "\tInputText\x12\x1a.sanderling.driver.v1.Text\x1a\x1b.sanderling.driver.v1.Empty\x12H\n" + + "\x05Swipe\x12\".sanderling.driver.v1.SwipeRequest\x1a\x1b.sanderling.driver.v1.Empty\x12N\n" + + "\bPressKey\x12%.sanderling.driver.v1.PressKeyRequest\x1a\x1b.sanderling.driver.v1.Empty\x12F\n" + "\n" + - "Screenshot\x12\x15.uatu.driver.v1.Empty\x1a\x15.uatu.driver.v1.Image\x12A\n" + - "\tHierarchy\x12\x15.uatu.driver.v1.Empty\x1a\x1d.uatu.driver.v1.HierarchyJSON\x12K\n" + + "Screenshot\x12\x1b.sanderling.driver.v1.Empty\x1a\x1b.sanderling.driver.v1.Image\x12M\n" + + "\tHierarchy\x12\x1b.sanderling.driver.v1.Empty\x1a#.sanderling.driver.v1.HierarchyJSON\x12W\n" + "\n" + - "RecentLogs\x12!.uatu.driver.v1.RecentLogsRequest\x1a\x1a.uatu.driver.v1.LogEntries\x12>\n" + - "\vWaitForIdle\x12\x18.uatu.driver.v1.Duration\x1a\x15.uatu.driver.v1.Empty\x12=\n" + - "\x06Health\x12\x15.uatu.driver.v1.Empty\x1a\x1c.uatu.driver.v1.HealthStatus\x12J\n" + - "\aMetrics\x12\x1e.uatu.driver.v1.MetricsRequest\x1a\x1f.uatu.driver.v1.MetricsResponseBM\n" + - "\x12dev.uatu.driver.v1P\x01Z5github.com/priyanshujain/uatu/proto/driverpb;driverpbb\x06proto3" + "RecentLogs\x12'.sanderling.driver.v1.RecentLogsRequest\x1a .sanderling.driver.v1.LogEntries\x12J\n" + + "\vWaitForIdle\x12\x1e.sanderling.driver.v1.Duration\x1a\x1b.sanderling.driver.v1.Empty\x12I\n" + + "\x06Health\x12\x1b.sanderling.driver.v1.Empty\x1a\".sanderling.driver.v1.HealthStatus\x12V\n" + + "\aMetrics\x12$.sanderling.driver.v1.MetricsRequest\x1a%.sanderling.driver.v1.MetricsResponseBY\n" + + "\x18dev.sanderling.driver.v1P\x01Z;github.com/priyanshujain/sanderling/proto/driverpb;driverpbb\x06proto3" var ( file_driverpb_driver_proto_rawDescOnce sync.Once @@ -933,53 +933,53 @@ func file_driverpb_driver_proto_rawDescGZIP() []byte { var file_driverpb_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_driverpb_driver_proto_goTypes = []any{ - (*Empty)(nil), // 0: uatu.driver.v1.Empty - (*LaunchRequest)(nil), // 1: uatu.driver.v1.LaunchRequest - (*Point)(nil), // 2: uatu.driver.v1.Point - (*Text)(nil), // 3: uatu.driver.v1.Text - (*Selector)(nil), // 4: uatu.driver.v1.Selector - (*Image)(nil), // 5: uatu.driver.v1.Image - (*HierarchyJSON)(nil), // 6: uatu.driver.v1.HierarchyJSON - (*Duration)(nil), // 7: uatu.driver.v1.Duration - (*HealthStatus)(nil), // 8: uatu.driver.v1.HealthStatus - (*SwipeRequest)(nil), // 9: uatu.driver.v1.SwipeRequest - (*PressKeyRequest)(nil), // 10: uatu.driver.v1.PressKeyRequest - (*RecentLogsRequest)(nil), // 11: uatu.driver.v1.RecentLogsRequest - (*LogEntries)(nil), // 12: uatu.driver.v1.LogEntries - (*LogEntry)(nil), // 13: uatu.driver.v1.LogEntry - (*MetricsRequest)(nil), // 14: uatu.driver.v1.MetricsRequest - (*MetricsResponse)(nil), // 15: uatu.driver.v1.MetricsResponse + (*Empty)(nil), // 0: sanderling.driver.v1.Empty + (*LaunchRequest)(nil), // 1: sanderling.driver.v1.LaunchRequest + (*Point)(nil), // 2: sanderling.driver.v1.Point + (*Text)(nil), // 3: sanderling.driver.v1.Text + (*Selector)(nil), // 4: sanderling.driver.v1.Selector + (*Image)(nil), // 5: sanderling.driver.v1.Image + (*HierarchyJSON)(nil), // 6: sanderling.driver.v1.HierarchyJSON + (*Duration)(nil), // 7: sanderling.driver.v1.Duration + (*HealthStatus)(nil), // 8: sanderling.driver.v1.HealthStatus + (*SwipeRequest)(nil), // 9: sanderling.driver.v1.SwipeRequest + (*PressKeyRequest)(nil), // 10: sanderling.driver.v1.PressKeyRequest + (*RecentLogsRequest)(nil), // 11: sanderling.driver.v1.RecentLogsRequest + (*LogEntries)(nil), // 12: sanderling.driver.v1.LogEntries + (*LogEntry)(nil), // 13: sanderling.driver.v1.LogEntry + (*MetricsRequest)(nil), // 14: sanderling.driver.v1.MetricsRequest + (*MetricsResponse)(nil), // 15: sanderling.driver.v1.MetricsResponse } var file_driverpb_driver_proto_depIdxs = []int32{ - 2, // 0: uatu.driver.v1.SwipeRequest.from:type_name -> uatu.driver.v1.Point - 2, // 1: uatu.driver.v1.SwipeRequest.to:type_name -> uatu.driver.v1.Point - 13, // 2: uatu.driver.v1.LogEntries.entries:type_name -> uatu.driver.v1.LogEntry - 1, // 3: uatu.driver.v1.Driver.Launch:input_type -> uatu.driver.v1.LaunchRequest - 0, // 4: uatu.driver.v1.Driver.Terminate:input_type -> uatu.driver.v1.Empty - 2, // 5: uatu.driver.v1.Driver.Tap:input_type -> uatu.driver.v1.Point - 4, // 6: uatu.driver.v1.Driver.TapSelector:input_type -> uatu.driver.v1.Selector - 3, // 7: uatu.driver.v1.Driver.InputText:input_type -> uatu.driver.v1.Text - 9, // 8: uatu.driver.v1.Driver.Swipe:input_type -> uatu.driver.v1.SwipeRequest - 10, // 9: uatu.driver.v1.Driver.PressKey:input_type -> uatu.driver.v1.PressKeyRequest - 0, // 10: uatu.driver.v1.Driver.Screenshot:input_type -> uatu.driver.v1.Empty - 0, // 11: uatu.driver.v1.Driver.Hierarchy:input_type -> uatu.driver.v1.Empty - 11, // 12: uatu.driver.v1.Driver.RecentLogs:input_type -> uatu.driver.v1.RecentLogsRequest - 7, // 13: uatu.driver.v1.Driver.WaitForIdle:input_type -> uatu.driver.v1.Duration - 0, // 14: uatu.driver.v1.Driver.Health:input_type -> uatu.driver.v1.Empty - 14, // 15: uatu.driver.v1.Driver.Metrics:input_type -> uatu.driver.v1.MetricsRequest - 0, // 16: uatu.driver.v1.Driver.Launch:output_type -> uatu.driver.v1.Empty - 0, // 17: uatu.driver.v1.Driver.Terminate:output_type -> uatu.driver.v1.Empty - 0, // 18: uatu.driver.v1.Driver.Tap:output_type -> uatu.driver.v1.Empty - 0, // 19: uatu.driver.v1.Driver.TapSelector:output_type -> uatu.driver.v1.Empty - 0, // 20: uatu.driver.v1.Driver.InputText:output_type -> uatu.driver.v1.Empty - 0, // 21: uatu.driver.v1.Driver.Swipe:output_type -> uatu.driver.v1.Empty - 0, // 22: uatu.driver.v1.Driver.PressKey:output_type -> uatu.driver.v1.Empty - 5, // 23: uatu.driver.v1.Driver.Screenshot:output_type -> uatu.driver.v1.Image - 6, // 24: uatu.driver.v1.Driver.Hierarchy:output_type -> uatu.driver.v1.HierarchyJSON - 12, // 25: uatu.driver.v1.Driver.RecentLogs:output_type -> uatu.driver.v1.LogEntries - 0, // 26: uatu.driver.v1.Driver.WaitForIdle:output_type -> uatu.driver.v1.Empty - 8, // 27: uatu.driver.v1.Driver.Health:output_type -> uatu.driver.v1.HealthStatus - 15, // 28: uatu.driver.v1.Driver.Metrics:output_type -> uatu.driver.v1.MetricsResponse + 2, // 0: sanderling.driver.v1.SwipeRequest.from:type_name -> sanderling.driver.v1.Point + 2, // 1: sanderling.driver.v1.SwipeRequest.to:type_name -> sanderling.driver.v1.Point + 13, // 2: sanderling.driver.v1.LogEntries.entries:type_name -> sanderling.driver.v1.LogEntry + 1, // 3: sanderling.driver.v1.Driver.Launch:input_type -> sanderling.driver.v1.LaunchRequest + 0, // 4: sanderling.driver.v1.Driver.Terminate:input_type -> sanderling.driver.v1.Empty + 2, // 5: sanderling.driver.v1.Driver.Tap:input_type -> sanderling.driver.v1.Point + 4, // 6: sanderling.driver.v1.Driver.TapSelector:input_type -> sanderling.driver.v1.Selector + 3, // 7: sanderling.driver.v1.Driver.InputText:input_type -> sanderling.driver.v1.Text + 9, // 8: sanderling.driver.v1.Driver.Swipe:input_type -> sanderling.driver.v1.SwipeRequest + 10, // 9: sanderling.driver.v1.Driver.PressKey:input_type -> sanderling.driver.v1.PressKeyRequest + 0, // 10: sanderling.driver.v1.Driver.Screenshot:input_type -> sanderling.driver.v1.Empty + 0, // 11: sanderling.driver.v1.Driver.Hierarchy:input_type -> sanderling.driver.v1.Empty + 11, // 12: sanderling.driver.v1.Driver.RecentLogs:input_type -> sanderling.driver.v1.RecentLogsRequest + 7, // 13: sanderling.driver.v1.Driver.WaitForIdle:input_type -> sanderling.driver.v1.Duration + 0, // 14: sanderling.driver.v1.Driver.Health:input_type -> sanderling.driver.v1.Empty + 14, // 15: sanderling.driver.v1.Driver.Metrics:input_type -> sanderling.driver.v1.MetricsRequest + 0, // 16: sanderling.driver.v1.Driver.Launch:output_type -> sanderling.driver.v1.Empty + 0, // 17: sanderling.driver.v1.Driver.Terminate:output_type -> sanderling.driver.v1.Empty + 0, // 18: sanderling.driver.v1.Driver.Tap:output_type -> sanderling.driver.v1.Empty + 0, // 19: sanderling.driver.v1.Driver.TapSelector:output_type -> sanderling.driver.v1.Empty + 0, // 20: sanderling.driver.v1.Driver.InputText:output_type -> sanderling.driver.v1.Empty + 0, // 21: sanderling.driver.v1.Driver.Swipe:output_type -> sanderling.driver.v1.Empty + 0, // 22: sanderling.driver.v1.Driver.PressKey:output_type -> sanderling.driver.v1.Empty + 5, // 23: sanderling.driver.v1.Driver.Screenshot:output_type -> sanderling.driver.v1.Image + 6, // 24: sanderling.driver.v1.Driver.Hierarchy:output_type -> sanderling.driver.v1.HierarchyJSON + 12, // 25: sanderling.driver.v1.Driver.RecentLogs:output_type -> sanderling.driver.v1.LogEntries + 0, // 26: sanderling.driver.v1.Driver.WaitForIdle:output_type -> sanderling.driver.v1.Empty + 8, // 27: sanderling.driver.v1.Driver.Health:output_type -> sanderling.driver.v1.HealthStatus + 15, // 28: sanderling.driver.v1.Driver.Metrics:output_type -> sanderling.driver.v1.MetricsResponse 16, // [16:29] is the sub-list for method output_type 3, // [3:16] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name diff --git a/proto/driverpb/driver.proto b/proto/driverpb/driver.proto index a6f014b..9451e7c 100644 --- a/proto/driverpb/driver.proto +++ b/proto/driverpb/driver.proto @@ -1,9 +1,9 @@ syntax = "proto3"; -package uatu.driver.v1; +package sanderling.driver.v1; -option go_package = "github.com/priyanshujain/uatu/proto/driverpb;driverpb"; -option java_package = "dev.uatu.driver.v1"; +option go_package = "github.com/priyanshujain/sanderling/proto/driverpb;driverpb"; +option java_package = "dev.sanderling.driver.v1"; option java_multiple_files = true; service Driver { diff --git a/proto/driverpb/driver_grpc.pb.go b/proto/driverpb/driver_grpc.pb.go index a7f9612..088da2d 100644 --- a/proto/driverpb/driver_grpc.pb.go +++ b/proto/driverpb/driver_grpc.pb.go @@ -19,19 +19,19 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - Driver_Launch_FullMethodName = "/uatu.driver.v1.Driver/Launch" - Driver_Terminate_FullMethodName = "/uatu.driver.v1.Driver/Terminate" - Driver_Tap_FullMethodName = "/uatu.driver.v1.Driver/Tap" - Driver_TapSelector_FullMethodName = "/uatu.driver.v1.Driver/TapSelector" - Driver_InputText_FullMethodName = "/uatu.driver.v1.Driver/InputText" - Driver_Swipe_FullMethodName = "/uatu.driver.v1.Driver/Swipe" - Driver_PressKey_FullMethodName = "/uatu.driver.v1.Driver/PressKey" - Driver_Screenshot_FullMethodName = "/uatu.driver.v1.Driver/Screenshot" - Driver_Hierarchy_FullMethodName = "/uatu.driver.v1.Driver/Hierarchy" - Driver_RecentLogs_FullMethodName = "/uatu.driver.v1.Driver/RecentLogs" - Driver_WaitForIdle_FullMethodName = "/uatu.driver.v1.Driver/WaitForIdle" - Driver_Health_FullMethodName = "/uatu.driver.v1.Driver/Health" - Driver_Metrics_FullMethodName = "/uatu.driver.v1.Driver/Metrics" + Driver_Launch_FullMethodName = "/sanderling.driver.v1.Driver/Launch" + Driver_Terminate_FullMethodName = "/sanderling.driver.v1.Driver/Terminate" + Driver_Tap_FullMethodName = "/sanderling.driver.v1.Driver/Tap" + Driver_TapSelector_FullMethodName = "/sanderling.driver.v1.Driver/TapSelector" + Driver_InputText_FullMethodName = "/sanderling.driver.v1.Driver/InputText" + Driver_Swipe_FullMethodName = "/sanderling.driver.v1.Driver/Swipe" + Driver_PressKey_FullMethodName = "/sanderling.driver.v1.Driver/PressKey" + Driver_Screenshot_FullMethodName = "/sanderling.driver.v1.Driver/Screenshot" + Driver_Hierarchy_FullMethodName = "/sanderling.driver.v1.Driver/Hierarchy" + Driver_RecentLogs_FullMethodName = "/sanderling.driver.v1.Driver/RecentLogs" + Driver_WaitForIdle_FullMethodName = "/sanderling.driver.v1.Driver/WaitForIdle" + Driver_Health_FullMethodName = "/sanderling.driver.v1.Driver/Health" + Driver_Metrics_FullMethodName = "/sanderling.driver.v1.Driver/Metrics" ) // DriverClient is the client API for Driver service. @@ -516,7 +516,7 @@ func _Driver_Metrics_Handler(srv interface{}, ctx context.Context, dec func(inte // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var Driver_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "uatu.driver.v1.Driver", + ServiceName: "sanderling.driver.v1.Driver", HandlerType: (*DriverServer)(nil), Methods: []grpc.MethodDesc{ { diff --git a/proto/driverpb/driver_test.go b/proto/driverpb/driver_test.go index 46f1aaf..6ca1bd0 100644 --- a/proto/driverpb/driver_test.go +++ b/proto/driverpb/driver_test.go @@ -8,7 +8,7 @@ import ( func TestDriverServiceDescriptor(t *testing.T) { var sd grpc.ServiceDesc = Driver_ServiceDesc - if sd.ServiceName != "uatu.driver.v1.Driver" { + if sd.ServiceName != "sanderling.driver.v1.Driver" { t.Fatalf("unexpected service name: %q", sd.ServiceName) } diff --git a/sdk/android/build.gradle.kts b/sdk/android/build.gradle.kts index 33bb357..6ded7f8 100644 --- a/sdk/android/build.gradle.kts +++ b/sdk/android/build.gradle.kts @@ -10,11 +10,11 @@ plugins { id("org.jetbrains.dokka-javadoc") version "2.2.0" } -version = findProperty("uatu.version") as String? ?: "0.0.0-dev" +version = findProperty("sanderling.version") as String? ?: "0.0.0-dev" group = "io.github.priyanshujain" android { - namespace = "dev.uatu.sdk" + namespace = "dev.sanderling.sdk" compileSdk = 35 defaultConfig { @@ -61,12 +61,12 @@ mavenPublishing { ) pom { - name.set("uatu sdk-android") + name.set("sanderling sdk-android") description.set( - "Android runtime SDK for uatu, a property-based UI fuzzer for mobile apps. " + - "Exposes a content-provider accessibility bridge consumed by the uatu CLI at test time.", + "Android runtime SDK for sanderling, a property-based UI fuzzer for mobile apps. " + + "Exposes a content-provider accessibility bridge consumed by the sanderling CLI at test time.", ) - url.set("https://github.com/priyanshujain/uatu") + url.set("https://github.com/priyanshujain/sanderling") licenses { license { @@ -85,9 +85,9 @@ mavenPublishing { } scm { - url.set("https://github.com/priyanshujain/uatu") - connection.set("scm:git:git://github.com/priyanshujain/uatu.git") - developerConnection.set("scm:git:ssh://git@github.com/priyanshujain/uatu.git") + url.set("https://github.com/priyanshujain/sanderling") + connection.set("scm:git:git://github.com/priyanshujain/sanderling.git") + developerConnection.set("scm:git:ssh://git@github.com/priyanshujain/sanderling.git") } } } diff --git a/sdk/android/consumer-rules.pro b/sdk/android/consumer-rules.pro index 0f94388..0b2914b 100644 --- a/sdk/android/consumer-rules.pro +++ b/sdk/android/consumer-rules.pro @@ -1,2 +1,2 @@ -# ProGuard rules shipped to consumers of dev.uatu:sdk-android. +# ProGuard rules shipped to consumers of dev.sanderling:sdk-android. # None needed for v0.1. Socket and semaphore APIs are all reflection-free. diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/ChoreographerPoster.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/ChoreographerPoster.kt similarity index 93% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/ChoreographerPoster.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/ChoreographerPoster.kt index f05eb69..6a2a939 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/ChoreographerPoster.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/ChoreographerPoster.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import android.os.Handler import android.os.Looper diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/ExceptionRecorder.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/ExceptionRecorder.kt similarity index 98% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/ExceptionRecorder.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/ExceptionRecorder.kt index 29992da..a7e2ee7 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/ExceptionRecorder.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/ExceptionRecorder.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.io.PrintWriter import java.io.StringWriter diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/LocalAbstractTransport.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/LocalAbstractTransport.kt similarity index 97% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/LocalAbstractTransport.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/LocalAbstractTransport.kt index c945c82..36ff117 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/LocalAbstractTransport.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/LocalAbstractTransport.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import android.net.LocalSocket import android.net.LocalSocketAddress diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/Pauser.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/Pauser.kt similarity index 98% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/Pauser.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/Pauser.kt index e6008f6..bcfaec3 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/Pauser.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/Pauser.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.util.concurrent.CountDownLatch import java.util.concurrent.Semaphore diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/Protocol.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/Protocol.kt similarity index 99% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/Protocol.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/Protocol.kt index 9959476..f7160b4 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/Protocol.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/Protocol.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.io.DataInputStream import java.io.DataOutputStream diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/Uatu.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/Sanderling.kt similarity index 80% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/Uatu.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/Sanderling.kt index a1e17ec..13189da 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/Uatu.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/Sanderling.kt @@ -1,24 +1,24 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import android.app.Application import android.util.Log data class Configuration( - val socketName: String = "uatu-agent", + val socketName: String = "sanderling-agent", val pauseTimeoutMillis: Long = 5_000L, ) -object Uatu { +object Sanderling { const val VERSION: String = "0.0.1" - private const val LOG_TAG = "Uatu" + private const val LOG_TAG = "Sanderling" - @Volatile private var runtime: UatuRuntime? = null + @Volatile private var runtime: SanderlingRuntime? = null @JvmOverloads @Synchronized fun start(application: Application, configuration: Configuration = Configuration()) { if (runtime != null) return - val newRuntime = UatuRuntime( + val newRuntime = SanderlingRuntime( transport = LocalAbstractTransport(configuration.socketName), pauser = Pauser(ChoreographerPoster(), configuration.pauseTimeoutMillis), version = VERSION, @@ -32,7 +32,7 @@ object Uatu { fun extract(name: String, function: () -> Any?) { val activeRuntime = runtime - ?: throw IllegalStateException("Uatu.start must be called before registering extractors") + ?: throw IllegalStateException("Sanderling.start must be called before registering extractors") activeRuntime.register(name, function) } diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/UatuRuntime.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/SanderlingRuntime.kt similarity index 95% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/UatuRuntime.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/SanderlingRuntime.kt index 11597f1..52e54b4 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/UatuRuntime.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/SanderlingRuntime.kt @@ -1,8 +1,8 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import android.util.Log -internal class UatuRuntime( +internal class SanderlingRuntime( transport: AgentTransport, private val pauser: Pauser, private val version: String, @@ -45,7 +45,7 @@ internal class UatuRuntime( private inner class AgentHandler : SocketClient.Handler { override fun onConnected(sender: SocketClient.MessageSender) { - this@UatuRuntime.sender = sender + this@SanderlingRuntime.sender = sender try { sender.send(Message.hello(version, platform, appPackage)) } catch (cause: Exception) { @@ -92,6 +92,6 @@ internal class UatuRuntime( } companion object { - private const val LOG_TAG = "Uatu" + private const val LOG_TAG = "Sanderling" } } diff --git a/sdk/android/src/main/kotlin/dev/uatu/sdk/SocketClient.kt b/sdk/android/src/main/kotlin/dev/sanderling/sdk/SocketClient.kt similarity index 97% rename from sdk/android/src/main/kotlin/dev/uatu/sdk/SocketClient.kt rename to sdk/android/src/main/kotlin/dev/sanderling/sdk/SocketClient.kt index 4a0d556..fd8baf8 100644 --- a/sdk/android/src/main/kotlin/dev/uatu/sdk/SocketClient.kt +++ b/sdk/android/src/main/kotlin/dev/sanderling/sdk/SocketClient.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.io.IOException import java.io.InputStream @@ -30,7 +30,7 @@ class SocketClient( private val transport: AgentTransport, private val handler: Handler, private val backoff: Backoff = Backoff(), - private val threadFactory: (Runnable) -> Thread = { runnable -> Thread(runnable, "uatu-agent-reader") }, + private val threadFactory: (Runnable) -> Thread = { runnable -> Thread(runnable, "sanderling-agent-reader") }, private val sleeper: (Long) -> Unit = { millis -> if (millis > 0L) Thread.sleep(millis) }, ) { interface Handler { diff --git a/sdk/android/src/test/kotlin/dev/uatu/sdk/ExceptionRecorderTest.kt b/sdk/android/src/test/kotlin/dev/sanderling/sdk/ExceptionRecorderTest.kt similarity index 98% rename from sdk/android/src/test/kotlin/dev/uatu/sdk/ExceptionRecorderTest.kt rename to sdk/android/src/test/kotlin/dev/sanderling/sdk/ExceptionRecorderTest.kt index f5b133d..78f54fe 100644 --- a/sdk/android/src/test/kotlin/dev/uatu/sdk/ExceptionRecorderTest.kt +++ b/sdk/android/src/test/kotlin/dev/sanderling/sdk/ExceptionRecorderTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/sdk/android/src/test/kotlin/dev/uatu/sdk/PauserTest.kt b/sdk/android/src/test/kotlin/dev/sanderling/sdk/PauserTest.kt similarity index 99% rename from sdk/android/src/test/kotlin/dev/uatu/sdk/PauserTest.kt rename to sdk/android/src/test/kotlin/dev/sanderling/sdk/PauserTest.kt index 9f6f29f..281cfb0 100644 --- a/sdk/android/src/test/kotlin/dev/uatu/sdk/PauserTest.kt +++ b/sdk/android/src/test/kotlin/dev/sanderling/sdk/PauserTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.util.concurrent.CountDownLatch import java.util.concurrent.Executors diff --git a/sdk/android/src/test/kotlin/dev/uatu/sdk/ProtocolTest.kt b/sdk/android/src/test/kotlin/dev/sanderling/sdk/ProtocolTest.kt similarity index 99% rename from sdk/android/src/test/kotlin/dev/uatu/sdk/ProtocolTest.kt rename to sdk/android/src/test/kotlin/dev/sanderling/sdk/ProtocolTest.kt index 1370c63..dc900db 100644 --- a/sdk/android/src/test/kotlin/dev/uatu/sdk/ProtocolTest.kt +++ b/sdk/android/src/test/kotlin/dev/sanderling/sdk/ProtocolTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream diff --git a/sdk/android/src/test/kotlin/dev/uatu/sdk/UatuRuntimeTest.kt b/sdk/android/src/test/kotlin/dev/sanderling/sdk/SanderlingRuntimeTest.kt similarity index 94% rename from sdk/android/src/test/kotlin/dev/uatu/sdk/UatuRuntimeTest.kt rename to sdk/android/src/test/kotlin/dev/sanderling/sdk/SanderlingRuntimeTest.kt index f6499b6..438425e 100644 --- a/sdk/android/src/test/kotlin/dev/uatu/sdk/UatuRuntimeTest.kt +++ b/sdk/android/src/test/kotlin/dev/sanderling/sdk/SanderlingRuntimeTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CountDownLatch @@ -12,22 +12,22 @@ import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Test -class UatuRuntimeTest { +class SanderlingRuntimeTest { private lateinit var transport: SocketClientTest.FakeTransport private lateinit var frameThread: PauserTest.FakeFrameThread - private lateinit var runtime: UatuRuntime + private lateinit var runtime: SanderlingRuntime - private fun newRuntime(): UatuRuntime { + private fun newRuntime(): SanderlingRuntime { transport = SocketClientTest.FakeTransport() frameThread = PauserTest.FakeFrameThread() val pauser = Pauser(frameThread, pauseTimeoutMillis = 2_000L) - return UatuRuntime( + return SanderlingRuntime( transport = transport, pauser = pauser, version = "0.0.1", platform = "android", - appPackage = "com.example.uatu_test", + appPackage = "com.example.sanderling_test", ).also { runtime = it } } @@ -43,7 +43,7 @@ class UatuRuntimeTest { assertEquals(MessageType.HELLO, hello.type) assertEquals("0.0.1", hello.version) assertEquals("android", hello.platform) - assertEquals("com.example.uatu_test", hello.appPackage) + assertEquals("com.example.sanderling_test", hello.appPackage) } @Test fun pauseTriggersExtractorsAndReturnsState() { diff --git a/sdk/android/src/test/kotlin/dev/uatu/sdk/SocketClientTest.kt b/sdk/android/src/test/kotlin/dev/sanderling/sdk/SocketClientTest.kt similarity index 99% rename from sdk/android/src/test/kotlin/dev/uatu/sdk/SocketClientTest.kt rename to sdk/android/src/test/kotlin/dev/sanderling/sdk/SocketClientTest.kt index 36d3d34..fdc5035 100644 --- a/sdk/android/src/test/kotlin/dev/uatu/sdk/SocketClientTest.kt +++ b/sdk/android/src/test/kotlin/dev/sanderling/sdk/SocketClientTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sdk +package dev.sanderling.sdk import java.io.IOException import java.io.PipedInputStream diff --git a/settings.gradle.kts b/settings.gradle.kts index 030f14c..36dd1b3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,7 +14,7 @@ dependencyResolutionManagement { } } -rootProject.name = "uatu" +rootProject.name = "sanderling" include(":sidecar") include(":sdk-android") diff --git a/sidecar/build.gradle.kts b/sidecar/build.gradle.kts index b724519..41b24d7 100644 --- a/sidecar/build.gradle.kts +++ b/sidecar/build.gradle.kts @@ -7,7 +7,7 @@ plugins { id("com.google.protobuf") version "0.9.5" } -version = findProperty("uatu.version") as String? ?: "0.0.0-dev" +version = findProperty("sanderling.version") as String? ?: "0.0.0-dev" java { toolchain { @@ -70,7 +70,7 @@ sourceSets { } application { - mainClass.set("dev.uatu.sidecar.MainKt") + mainClass.set("dev.sanderling.sidecar.MainKt") } // The Go binary embeds this fat JAR by fixed path (internal/sidecar/assets/ diff --git a/sidecar/src/main/kotlin/dev/uatu/sidecar/DriverBackend.kt b/sidecar/src/main/kotlin/dev/sanderling/sidecar/DriverBackend.kt similarity index 99% rename from sidecar/src/main/kotlin/dev/uatu/sidecar/DriverBackend.kt rename to sidecar/src/main/kotlin/dev/sanderling/sidecar/DriverBackend.kt index 7975482..9a36a0e 100644 --- a/sidecar/src/main/kotlin/dev/uatu/sidecar/DriverBackend.kt +++ b/sidecar/src/main/kotlin/dev/sanderling/sidecar/DriverBackend.kt @@ -1,4 +1,4 @@ -package dev.uatu.sidecar +package dev.sanderling.sidecar interface DriverBackend { fun launch(bundleId: String, launcherActivity: String, clearState: Boolean) diff --git a/sidecar/src/main/kotlin/dev/uatu/sidecar/DriverService.kt b/sidecar/src/main/kotlin/dev/sanderling/sidecar/DriverService.kt similarity index 86% rename from sidecar/src/main/kotlin/dev/uatu/sidecar/DriverService.kt rename to sidecar/src/main/kotlin/dev/sanderling/sidecar/DriverService.kt index 1c5b844..40f2294 100644 --- a/sidecar/src/main/kotlin/dev/uatu/sidecar/DriverService.kt +++ b/sidecar/src/main/kotlin/dev/sanderling/sidecar/DriverService.kt @@ -1,23 +1,23 @@ -package dev.uatu.sidecar +package dev.sanderling.sidecar import com.google.protobuf.ByteString -import dev.uatu.driver.v1.DriverGrpc -import dev.uatu.driver.v1.Duration -import dev.uatu.driver.v1.Empty -import dev.uatu.driver.v1.HealthStatus -import dev.uatu.driver.v1.HierarchyJSON -import dev.uatu.driver.v1.Image -import dev.uatu.driver.v1.LaunchRequest -import dev.uatu.driver.v1.LogEntries -import dev.uatu.driver.v1.LogEntry -import dev.uatu.driver.v1.MetricsRequest -import dev.uatu.driver.v1.MetricsResponse -import dev.uatu.driver.v1.Point -import dev.uatu.driver.v1.PressKeyRequest -import dev.uatu.driver.v1.RecentLogsRequest -import dev.uatu.driver.v1.Selector -import dev.uatu.driver.v1.SwipeRequest -import dev.uatu.driver.v1.Text +import dev.sanderling.driver.v1.DriverGrpc +import dev.sanderling.driver.v1.Duration +import dev.sanderling.driver.v1.Empty +import dev.sanderling.driver.v1.HealthStatus +import dev.sanderling.driver.v1.HierarchyJSON +import dev.sanderling.driver.v1.Image +import dev.sanderling.driver.v1.LaunchRequest +import dev.sanderling.driver.v1.LogEntries +import dev.sanderling.driver.v1.LogEntry +import dev.sanderling.driver.v1.MetricsRequest +import dev.sanderling.driver.v1.MetricsResponse +import dev.sanderling.driver.v1.Point +import dev.sanderling.driver.v1.PressKeyRequest +import dev.sanderling.driver.v1.RecentLogsRequest +import dev.sanderling.driver.v1.Selector +import dev.sanderling.driver.v1.SwipeRequest +import dev.sanderling.driver.v1.Text import io.grpc.stub.StreamObserver import java.util.concurrent.atomic.AtomicReference diff --git a/sidecar/src/main/kotlin/dev/uatu/sidecar/Main.kt b/sidecar/src/main/kotlin/dev/sanderling/sidecar/Main.kt similarity index 92% rename from sidecar/src/main/kotlin/dev/uatu/sidecar/Main.kt rename to sidecar/src/main/kotlin/dev/sanderling/sidecar/Main.kt index b245ff8..db3b40a 100644 --- a/sidecar/src/main/kotlin/dev/uatu/sidecar/Main.kt +++ b/sidecar/src/main/kotlin/dev/sanderling/sidecar/Main.kt @@ -1,4 +1,4 @@ -package dev.uatu.sidecar +package dev.sanderling.sidecar import io.grpc.Server import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder @@ -48,7 +48,7 @@ fun main(arguments: Array) { val service = DriverService(platform = platform, serial = serial) val server = SidecarServer(port, service) val boundPort = server.start() - println("uatu-sidecar listening on 127.0.0.1:$boundPort platform=$platform") + println("sanderling-sidecar listening on 127.0.0.1:$boundPort platform=$platform") System.out.flush() server.awaitTermination() } diff --git a/sidecar/src/test/kotlin/dev/uatu/sidecar/DriverServiceTest.kt b/sidecar/src/test/kotlin/dev/sanderling/sidecar/DriverServiceTest.kt similarity index 93% rename from sidecar/src/test/kotlin/dev/uatu/sidecar/DriverServiceTest.kt rename to sidecar/src/test/kotlin/dev/sanderling/sidecar/DriverServiceTest.kt index 03b6fa0..7d43f63 100644 --- a/sidecar/src/test/kotlin/dev/uatu/sidecar/DriverServiceTest.kt +++ b/sidecar/src/test/kotlin/dev/sanderling/sidecar/DriverServiceTest.kt @@ -1,14 +1,14 @@ -package dev.uatu.sidecar +package dev.sanderling.sidecar -import dev.uatu.driver.v1.DriverGrpc -import dev.uatu.driver.v1.Duration -import dev.uatu.driver.v1.Empty -import dev.uatu.driver.v1.LaunchRequest -import dev.uatu.driver.v1.Point -import dev.uatu.driver.v1.PressKeyRequest -import dev.uatu.driver.v1.RecentLogsRequest -import dev.uatu.driver.v1.SwipeRequest -import dev.uatu.driver.v1.Text +import dev.sanderling.driver.v1.DriverGrpc +import dev.sanderling.driver.v1.Duration +import dev.sanderling.driver.v1.Empty +import dev.sanderling.driver.v1.LaunchRequest +import dev.sanderling.driver.v1.Point +import dev.sanderling.driver.v1.PressKeyRequest +import dev.sanderling.driver.v1.RecentLogsRequest +import dev.sanderling.driver.v1.SwipeRequest +import dev.sanderling.driver.v1.Text import io.grpc.ManagedChannel import io.grpc.inprocess.InProcessChannelBuilder import io.grpc.inprocess.InProcessServerBuilder diff --git a/sidecar/src/test/kotlin/dev/uatu/sidecar/InputTextClearTest.kt b/sidecar/src/test/kotlin/dev/sanderling/sidecar/InputTextClearTest.kt similarity index 99% rename from sidecar/src/test/kotlin/dev/uatu/sidecar/InputTextClearTest.kt rename to sidecar/src/test/kotlin/dev/sanderling/sidecar/InputTextClearTest.kt index 5f29f0c..5efbce3 100644 --- a/sidecar/src/test/kotlin/dev/uatu/sidecar/InputTextClearTest.kt +++ b/sidecar/src/test/kotlin/dev/sanderling/sidecar/InputTextClearTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sidecar +package dev.sanderling.sidecar import org.junit.Test import kotlin.test.assertEquals diff --git a/sidecar/src/test/kotlin/dev/uatu/sidecar/ResolveActivityTest.kt b/sidecar/src/test/kotlin/dev/sanderling/sidecar/ResolveActivityTest.kt similarity index 97% rename from sidecar/src/test/kotlin/dev/uatu/sidecar/ResolveActivityTest.kt rename to sidecar/src/test/kotlin/dev/sanderling/sidecar/ResolveActivityTest.kt index e27cca9..5ffaab8 100644 --- a/sidecar/src/test/kotlin/dev/uatu/sidecar/ResolveActivityTest.kt +++ b/sidecar/src/test/kotlin/dev/sanderling/sidecar/ResolveActivityTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sidecar +package dev.sanderling.sidecar import org.junit.Test import kotlin.test.assertEquals diff --git a/sidecar/src/test/kotlin/dev/uatu/sidecar/SidecarServerTest.kt b/sidecar/src/test/kotlin/dev/sanderling/sidecar/SidecarServerTest.kt similarity index 93% rename from sidecar/src/test/kotlin/dev/uatu/sidecar/SidecarServerTest.kt rename to sidecar/src/test/kotlin/dev/sanderling/sidecar/SidecarServerTest.kt index 30aabd2..2a75eab 100644 --- a/sidecar/src/test/kotlin/dev/uatu/sidecar/SidecarServerTest.kt +++ b/sidecar/src/test/kotlin/dev/sanderling/sidecar/SidecarServerTest.kt @@ -1,4 +1,4 @@ -package dev.uatu.sidecar +package dev.sanderling.sidecar import kotlin.test.Test import kotlin.test.assertTrue diff --git a/web/bun.lock b/web/bun.lock index 4c873b3..fff0bad 100644 --- a/web/bun.lock +++ b/web/bun.lock @@ -3,7 +3,7 @@ "configVersion": 1, "workspaces": { "": { - "name": "@uatu/inspect-web", + "name": "@sanderling/inspect-web", "dependencies": { "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/web/index.html b/web/index.html index 1cd2f03..8fa93f0 100644 --- a/web/index.html +++ b/web/index.html @@ -3,7 +3,7 @@ - uatu inspect + sanderling inspect diff --git a/web/package.json b/web/package.json index c4158d8..dc933c8 100644 --- a/web/package.json +++ b/web/package.json @@ -1,5 +1,5 @@ { - "name": "@uatu/inspect-web", + "name": "@sanderling/inspect-web", "private": true, "version": "0.0.0", "type": "module", diff --git a/web/src/hooks/useTheme.ts b/web/src/hooks/useTheme.ts index 85cfc92..aab0d27 100644 --- a/web/src/hooks/useTheme.ts +++ b/web/src/hooks/useTheme.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; export type ThemeMode = "light" | "dark"; -const STORAGE_KEY = "uatu-inspect-theme"; +const STORAGE_KEY = "sanderling-inspect-theme"; function detectInitial(): ThemeMode { if (typeof window === "undefined") { diff --git a/web/src/routes/RunList.tsx b/web/src/routes/RunList.tsx index d74b75d..4b7e2d7 100644 --- a/web/src/routes/RunList.tsx +++ b/web/src/routes/RunList.tsx @@ -53,7 +53,7 @@ export default function RunList() { return
loading runs...
; } if (runs.length === 0) { - return
no runs yet. run `uatu pbt` to produce some.
; + return
no runs yet. run `sanderling test` to produce some.
; } return ( diff --git a/web/src/types.ts b/web/src/types.ts index b5990df..85af7c3 100644 --- a/web/src/types.ts +++ b/web/src/types.ts @@ -6,7 +6,7 @@ export interface Meta { bundle_id: string; started_at: string; ended_at?: string; - uatu_version: string; + sanderling_version: string; } export interface RunSummary {