1package main
2
3import (
4	"context"
5	"math/rand"
6	"strconv"
7	"sync"
8	"testing"
9
10	"github.com/containerd/containerd/errdefs"
11	"github.com/containerd/containerd/runtime/v2/task"
12	specs "github.com/opencontainers/runtime-spec/specs-go"
13)
14
15var _ = (shimPod)(&testShimPod{})
16
17type testShimPod struct {
18	id string
19
20	tasks sync.Map
21}
22
23func (tsp *testShimPod) ID() string {
24	return tsp.id
25}
26
27func (tsp *testShimPod) CreateTask(ctx context.Context, req *task.CreateTaskRequest, s *specs.Spec) (shimTask, error) {
28	return nil, errdefs.ErrNotImplemented
29}
30
31func (tsp *testShimPod) GetTask(tid string) (shimTask, error) {
32	v, loaded := tsp.tasks.Load(tid)
33	if loaded {
34		return v.(shimTask), nil
35	}
36	return nil, errdefs.ErrNotFound
37}
38
39func (tsp *testShimPod) KillTask(ctx context.Context, tid, eid string, signal uint32, all bool) error {
40	s, err := tsp.GetTask(tid)
41	if err != nil {
42		return err
43	}
44	return s.KillExec(ctx, eid, signal, all)
45}
46
47// Pod tests
48
49func setupTestPodWithFakes(t *testing.T) (*pod, *testShimTask) {
50	st := &testShimTask{
51		id:    t.Name(),
52		exec:  newTestShimExec(t.Name(), t.Name(), 10),
53		execs: make(map[string]*testShimExec),
54	}
55	// Add a 2nd exec
56	seid := strconv.Itoa(rand.Int())
57	st.execs[seid] = newTestShimExec(t.Name(), seid, int(rand.Int31()))
58	p := &pod{
59		id:          t.Name(),
60		sandboxTask: st,
61	}
62	return p, st
63}
64
65func setupTestTaskInPod(t *testing.T, p *pod) *testShimTask {
66	tid := strconv.Itoa(rand.Int())
67	wt := &testShimTask{
68		id:   tid,
69		exec: newTestShimExec(tid, tid, int(rand.Int31())),
70	}
71	p.workloadTasks.Store(wt.id, wt)
72	return wt
73}
74
75func Test_pod_ID(t *testing.T) {
76	p := pod{id: t.Name()}
77	id := p.ID()
78	if id != t.Name() {
79		t.Fatalf("pod should of returned ID: %s, got: %s", t.Name(), id)
80	}
81}
82
83func Test_pod_GetTask_SandboxID(t *testing.T) {
84	p, st := setupTestPodWithFakes(t)
85	t1, err := p.GetTask(t.Name())
86	if err != nil {
87		t.Fatalf("should not have failed, got: %v", err)
88	}
89	if t1 != st {
90		t.Fatal("should have returned sandbox task")
91	}
92}
93
94func Test_pod_GetTask_WorkloadID_NotCreated_Error(t *testing.T) {
95	p, _ := setupTestPodWithFakes(t)
96	t1, err := p.GetTask("thisshouldnotmatch")
97
98	verifyExpectedError(t, t1, err, errdefs.ErrNotFound)
99}
100
101func Test_pod_GetTask_WorkloadID_Created_Success(t *testing.T) {
102	p, _ := setupTestPodWithFakes(t)
103	t2 := setupTestTaskInPod(t, p)
104
105	resp, err := p.GetTask(t2.ID())
106	if err != nil {
107		t.Fatalf("should not have failed, got: %v", err)
108	}
109	if resp != t2 {
110		t.Fatal("should have returned workload task")
111	}
112}
113
114func Test_pod_KillTask_UnknownTaskID_Error(t *testing.T) {
115	p, _ := setupTestPodWithFakes(t)
116	err := p.KillTask(context.TODO(), "thisshouldnotmatch", "", 0xf, false)
117
118	verifyExpectedError(t, nil, err, errdefs.ErrNotFound)
119}
120
121func Test_pod_KillTask_SandboxID_UnknownExecID_Error(t *testing.T) {
122	p, _ := setupTestPodWithFakes(t)
123	err := p.KillTask(context.TODO(), t.Name(), "thisshouldnotmatch", 0xf, false)
124
125	verifyExpectedError(t, nil, err, errdefs.ErrNotFound)
126}
127
128func Test_pod_KillTask_SandboxID_InitExecID_Success(t *testing.T) {
129	p, _ := setupTestPodWithFakes(t)
130	err := p.KillTask(context.TODO(), t.Name(), "", 0xf, false)
131	if err != nil {
132		t.Fatalf("should not have failed, got: %v", err)
133	}
134}
135
136func Test_pod_KillTask_SandboxID_InitExecID_All_Success(t *testing.T) {
137	p, _ := setupTestPodWithFakes(t)
138	// Add two workload tasks
139	setupTestTaskInPod(t, p)
140	setupTestTaskInPod(t, p)
141	err := p.KillTask(context.TODO(), t.Name(), "", 0xf, true)
142	if err != nil {
143		t.Fatalf("should not have failed, got: %v", err)
144	}
145}
146
147func Test_pod_KillTask_SandboxID_2ndExecID_Success(t *testing.T) {
148	p, t1 := setupTestPodWithFakes(t)
149	for k := range t1.execs {
150		err := p.KillTask(context.TODO(), t.Name(), k, 0xf, false)
151		if err != nil {
152			t.Fatalf("should not have failed, got: %v", err)
153		}
154	}
155}
156
157func Test_pod_KillTask_SandboxID_2ndExecID_All_Error(t *testing.T) {
158	p, t1 := setupTestPodWithFakes(t)
159	for k := range t1.execs {
160		err := p.KillTask(context.TODO(), t.Name(), k, 0xf, true)
161
162		verifyExpectedError(t, nil, err, errdefs.ErrFailedPrecondition)
163	}
164}
165
166func Test_pod_KillTask_WorkloadID_InitExecID_Success(t *testing.T) {
167	p, _ := setupTestPodWithFakes(t)
168	t1 := setupTestTaskInPod(t, p)
169
170	err := p.KillTask(context.TODO(), t1.ID(), "", 0xf, false)
171	if err != nil {
172		t.Fatalf("should not have failed, got: %v", err)
173	}
174}
175
176func Test_pod_KillTask_WorkloadID_InitExecID_All_Success(t *testing.T) {
177	p, _ := setupTestPodWithFakes(t)
178	t1 := setupTestTaskInPod(t, p)
179
180	err := p.KillTask(context.TODO(), t1.ID(), "", 0xf, true)
181	if err != nil {
182		t.Fatalf("should not have failed, got: %v", err)
183	}
184}
185
186func Test_pod_KillTask_WorkloadID_2ndExecID_Success(t *testing.T) {
187	p, _ := setupTestPodWithFakes(t)
188	t1 := setupTestTaskInPod(t, p)
189
190	for k := range t1.execs {
191		err := p.KillTask(context.TODO(), t1.ID(), k, 0xf, false)
192		if err != nil {
193			t.Fatalf("should not have failed, got: %v", err)
194		}
195	}
196}
197
198func Test_pod_KillTask_WorkloadID_2ndExecID_All_Error(t *testing.T) {
199	p, _ := setupTestPodWithFakes(t)
200	t1 := setupTestTaskInPod(t, p)
201
202	for k := range t1.execs {
203		err := p.KillTask(context.TODO(), t1.ID(), k, 0xf, true)
204
205		verifyExpectedError(t, nil, err, errdefs.ErrFailedPrecondition)
206	}
207}
208