1// Copyright 2020 The Gitea Authors. All rights reserved.
2// Use of this source code is governed by a MIT-style
3// license that can be found in the LICENSE file.
4
5package process
6
7import (
8	"context"
9	"testing"
10	"time"
11
12	"github.com/stretchr/testify/assert"
13)
14
15func TestGetManager(t *testing.T) {
16	go func() {
17		// test race protection
18		_ = GetManager()
19	}()
20	pm := GetManager()
21	assert.NotNil(t, pm)
22}
23
24func TestManager_AddContext(t *testing.T) {
25	pm := Manager{processes: make(map[IDType]*Process), next: 1}
26
27	ctx, cancel := context.WithCancel(context.Background())
28	defer cancel()
29
30	p1Ctx, _, finished := pm.AddContext(ctx, "foo")
31	defer finished()
32	assert.NotEmpty(t, GetContext(p1Ctx).GetPID(), "expected to get non-empty pid")
33
34	p2Ctx, _, finished := pm.AddContext(p1Ctx, "bar")
35	defer finished()
36
37	assert.NotEmpty(t, GetContext(p2Ctx).GetPID(), "expected to get non-empty pid")
38
39	assert.NotEqual(t, GetContext(p1Ctx).GetPID(), GetContext(p2Ctx).GetPID(), "expected to get different pids %s == %s", GetContext(p2Ctx).GetPID(), GetContext(p1Ctx).GetPID())
40	assert.Equal(t, GetContext(p1Ctx).GetPID(), GetContext(p2Ctx).GetParent().GetPID(), "expected to get pid %s got %s", GetContext(p1Ctx).GetPID(), GetContext(p2Ctx).GetParent().GetPID())
41}
42
43func TestManager_Cancel(t *testing.T) {
44	pm := Manager{processes: make(map[IDType]*Process), next: 1}
45
46	ctx, _, finished := pm.AddContext(context.Background(), "foo")
47	defer finished()
48
49	pm.Cancel(GetPID(ctx))
50
51	select {
52	case <-ctx.Done():
53	default:
54		assert.Fail(t, "Cancel should cancel the provided context")
55	}
56	finished()
57
58	ctx, cancel, finished := pm.AddContext(context.Background(), "foo")
59	defer finished()
60
61	cancel()
62
63	select {
64	case <-ctx.Done():
65	default:
66		assert.Fail(t, "Cancel should cancel the provided context")
67	}
68	finished()
69}
70
71func TestManager_Remove(t *testing.T) {
72	pm := Manager{processes: make(map[IDType]*Process), next: 1}
73
74	ctx, cancel := context.WithCancel(context.Background())
75	defer cancel()
76
77	p1Ctx, _, finished := pm.AddContext(ctx, "foo")
78	defer finished()
79	assert.NotEmpty(t, GetContext(p1Ctx).GetPID(), "expected to have non-empty PID")
80
81	p2Ctx, _, finished := pm.AddContext(p1Ctx, "bar")
82	defer finished()
83
84	assert.NotEqual(t, GetContext(p1Ctx).GetPID(), GetContext(p2Ctx).GetPID(), "expected to get different pids got %s == %s", GetContext(p2Ctx).GetPID(), GetContext(p1Ctx).GetPID())
85
86	pm.Remove(GetPID(p2Ctx))
87
88	_, exists := pm.processes[GetPID(p2Ctx)]
89	assert.False(t, exists, "PID %d is in the list but shouldn't", GetPID(p2Ctx))
90}
91
92func TestExecTimeoutNever(t *testing.T) {
93
94	// TODO Investigate how to improve the time elapsed per round.
95	maxLoops := 10
96	for i := 1; i < maxLoops; i++ {
97		_, stderr, err := GetManager().ExecTimeout(5*time.Second, "ExecTimeout", "git", "--version")
98		if err != nil {
99			t.Fatalf("git --version: %v(%s)", err, stderr)
100		}
101	}
102}
103
104func TestExecTimeoutAlways(t *testing.T) {
105
106	maxLoops := 100
107	for i := 1; i < maxLoops; i++ {
108		_, stderr, err := GetManager().ExecTimeout(100*time.Microsecond, "ExecTimeout", "sleep", "5")
109		// TODO Simplify logging and errors to get precise error type. E.g. checking "if err != context.DeadlineExceeded".
110		if err == nil {
111			t.Fatalf("sleep 5 secs: %v(%s)", err, stderr)
112		}
113	}
114}
115