File size: 2,165 Bytes
6a7089a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package orchestrator

import (
	"context"
	"io"
	"testing"

	"github.com/pinchtab/pinchtab/internal/bridge"
	"github.com/pinchtab/pinchtab/internal/idutil"
)

type mockRunner struct {
	runCalled bool
	portAvail bool
	args      []string
}

type mockCmd struct {
	pid     int
	isAlive bool
}

func (m *mockCmd) Wait() error { return nil }
func (m *mockCmd) PID() int    { return m.pid }
func (m *mockCmd) Cancel()     {}

func (m *mockRunner) Run(ctx context.Context, binary string, args []string, env []string, stdout, stderr io.Writer) (Cmd, error) {
	m.runCalled = true
	m.args = append([]string(nil), args...)
	return &mockCmd{pid: 1234, isAlive: true}, nil
}

func (m *mockRunner) IsPortAvailable(port string) bool {
	return m.portAvail
}

func TestLaunch_Mocked(t *testing.T) {
	runner := &mockRunner{portAvail: true}
	o := NewOrchestratorWithRunner(t.TempDir(), runner)

	inst, err := o.Launch("test-prof", "9999", true, nil)
	if err != nil {
		t.Fatalf("Launch failed: %v", err)
	}

	if !runner.runCalled {
		t.Error("expected runner.Run to be called")
	}
	if len(runner.args) != 1 || runner.args[0] != "bridge" {
		t.Fatalf("expected child process args [bridge], got %v", runner.args)
	}
	if !idutil.IsValidID(inst.ID, "inst") {
		t.Errorf("expected ID format inst_XXXXXXXX, got %s", inst.ID)
	}
}

func TestLaunch_PortConflict(t *testing.T) {
	runner := &mockRunner{portAvail: false}
	o := NewOrchestratorWithRunner(t.TempDir(), runner)

	_, err := o.Launch("test-prof", "9999", true, nil)
	if err == nil {
		t.Fatal("expected error for unavailable port")
	}
}

func TestInstanceIsActive(t *testing.T) {
	tests := []struct {
		name   string
		inst   *InstanceInternal
		active bool
	}{
		{
			name: "starting",
			inst: &InstanceInternal{
				Instance: bridge.Instance{Status: "starting"},
			},
			active: true,
		},
		{
			name: "running",
			inst: &InstanceInternal{
				Instance: bridge.Instance{Status: "running"},
			},
			active: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := instanceIsActive(tt.inst); got != tt.active {
				t.Errorf("instanceIsActive() = %v, want %v", got, tt.active)
			}
		})
	}
}