PPysolate SpineREAD THE CODE · UNDERSTAND THE SYSTEM
课程与章节
源码索引 / CURRENT IMPLEMENTATION

cmd/walkthrough/main_test.go

97 行 · 点击行号可定位;函数链接随声明位置更新,不手填行号。

跳到函数 / 声明
package main

import (
	"context"
	"encoding/json"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	spine "pysolate-spine"
)

func TestNotificationScenariosUseRealGuest(t *testing.T) {
	artifact := filepath.Join("..", "..", "dist", "spine.wasm")
	wasm, err := os.ReadFile(artifact)
	if err != nil {
		t.Fatalf("real Guest artifact is required: %v; build dist/spine.wasm before this test", err)
	}

	cases := []struct {
		scenario  scenario
		status    string
		output    string
		delivered bool
	}{
		{normal, "sent", "Notification sent.\n", true},
		{denied, "denied", "Notification not sent: Host denied it.\n", false},
		{unknown, "unknown", "Notification outcome unknown; not retrying.\n", true},
	}
	for _, tc := range cases {
		t.Run(string(tc.scenario), func(t *testing.T) {
			host := newNotificationHost(tc.scenario)
			ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
			defer cancel()
			runner, err := spine.New(ctx, wasm, host.manifest())
			if err != nil {
				t.Fatal(err)
			}
			defer runner.Close(context.Background())
			source, err := os.ReadFile(filepath.Join("..", "..", "examples", "notification.py"))
			if err != nil {
				t.Fatal(err)
			}
			out, err := runner.Run(ctx, string(source), map[string]any{})
			if err != nil {
				t.Fatalf("Run returned error: %v", err)
			}
			if !strings.Contains(out.Stdout, tc.output) {
				t.Errorf("Guest stdout %q does not include %q", out.Stdout, tc.output)
			}
			var result struct {
				Report report `json:"report"`
				Status string `json:"notification_status"`
			}
			if err := json.Unmarshal(out.Value, &result); err != nil {
				t.Fatalf("decode Guest result %s: %v", out.Value, err)
			}
			if result.Report != (report{Title: "Daily summary", Items: 3}) || result.Status != tc.status {
				t.Errorf("Guest result = %+v, want report and status %q", result, tc.status)
			}
			if host.calls["get_report"] != 1 || host.calls["send_notification"] != 1 {
				t.Fatalf("Host call counts = %#v, want one call per tool", host.calls)
			}
			if got := string(host.args["get_report"][0]); got != "{}" {
				t.Errorf("get_report args = %s, want {}", got)
			}
			var notificationArgs struct {
				Message string `json:"message"`
			}
			if err := json.Unmarshal(host.args["send_notification"][0], &notificationArgs); err != nil {
				t.Fatal(err)
			}
			if notificationArgs.Message != "Daily summary: 3 items" {
				t.Errorf("notification args = %+v", notificationArgs)
			}
			if host.serviceDelivered != tc.delivered {
				t.Errorf("evaluation delivery = %t, want %t", host.serviceDelivered, tc.delivered)
			}
			if tc.scenario == unknown && (result.Status == "sent" || strings.Contains(out.Stdout, "Notification sent.")) {
				t.Errorf("unknown confirmation was presented as success: result=%s stdout=%q", out.Value, out.Stdout)
			}
		})
	}
}

func TestScenarioValidation(t *testing.T) {
	for _, valid := range []string{"normal", "denied", "unknown"} {
		if got, err := validScenario(valid); err != nil || string(got) != valid {
			t.Errorf("validScenario(%q) = %q, %v", valid, got, err)
		}
	}
	if _, err := validScenario("success-ish"); err == nil {
		t.Fatal("invalid scenario was accepted")
	}
}