Skip to content

Commit 40fa19a

Browse files
committed
add cpubench test
1 parent 3e77601 commit 40fa19a

2 files changed

Lines changed: 136 additions & 4 deletions

File tree

pkg/perf/cpubench/cpubench_task.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
"os/exec"
87

98
"github.com/threefoldtech/zosbase/pkg/perf"
9+
"github.com/threefoldtech/zosbase/pkg/perf/iperf" // Import for ExecWrapper
1010
"github.com/threefoldtech/zosbase/pkg/stubs"
1111
)
1212

1313
// CPUBenchmarkTask defines CPU benchmark task.
14-
type CPUBenchmarkTask struct{}
14+
type CPUBenchmarkTask struct {
15+
execWrapper iperf.ExecWrapper
16+
}
1517

1618
// CPUBenchmarkResult holds CPU benchmark results with the workloads number during the benchmark.
1719
type CPUBenchmarkResult struct {
@@ -25,7 +27,15 @@ var _ perf.Task = (*CPUBenchmarkTask)(nil)
2527

2628
// NewTask returns a new CPU benchmark task.
2729
func NewTask() perf.Task {
28-
return &CPUBenchmarkTask{}
30+
return &CPUBenchmarkTask{
31+
execWrapper: &iperf.RealExecWrapper{},
32+
}
33+
}
34+
35+
func NewTaskWithExecWrapper(execWrapper iperf.ExecWrapper) perf.Task {
36+
return &CPUBenchmarkTask{
37+
execWrapper: execWrapper,
38+
}
2939
}
3040

3141
// ID returns task ID.
@@ -50,7 +60,8 @@ func (c *CPUBenchmarkTask) Jitter() uint32 {
5060

5161
// Run executes the CPU benchmark.
5262
func (c *CPUBenchmarkTask) Run(ctx context.Context) (interface{}, error) {
53-
cpubenchOut, err := exec.CommandContext(ctx, "cpubench", "-j").CombinedOutput()
63+
cmd := c.execWrapper.CommandContext(ctx, "cpubench", "-j")
64+
cpubenchOut, err := cmd.CombinedOutput()
5465
if err != nil {
5566
return nil, fmt.Errorf("failed to execute cpubench command: %w", err)
5667
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package cpubench
2+
3+
import (
4+
"context"
5+
"encoding/binary"
6+
"errors"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
"github.com/threefoldtech/zbus"
12+
"github.com/threefoldtech/zosbase/pkg/mocks"
13+
"github.com/threefoldtech/zosbase/pkg/perf"
14+
"github.com/threefoldtech/zosbase/pkg/perf/iperf"
15+
"go.uber.org/mock/gomock"
16+
)
17+
18+
func TestCPUBenchmarkTask(t *testing.T) {
19+
t.Run("create new CPU benchmark task", func(t *testing.T) {
20+
task := NewTask()
21+
22+
assert.NotNil(t, task)
23+
assert.Equal(t, "cpu-benchmark", task.ID())
24+
assert.Equal(t, "0 0 */6 * * *", task.Cron()) // Every 6 hours
25+
assert.Contains(t, task.Description(), "CPU")
26+
assert.Equal(t, uint32(0), task.Jitter())
27+
})
28+
29+
t.Run("task implements perf.Task interface", func(t *testing.T) {
30+
var _ perf.Task = NewTask()
31+
})
32+
}
33+
34+
func TestCPUBenchmarkTask_Run(t *testing.T) {
35+
ctrl := gomock.NewController(t)
36+
defer ctrl.Finish()
37+
38+
mockExec := iperf.NewMockExecWrapper(ctrl)
39+
mockCmd := iperf.NewMockExecCmd(ctrl)
40+
task := NewTaskWithExecWrapper(mockExec).(*CPUBenchmarkTask)
41+
ctx := context.Background()
42+
mockZbus := mocks.NewMockClient(ctrl)
43+
ctx = perf.WithZbusClient(ctx, mockZbus)
44+
45+
mockExec.EXPECT().CommandContext(ctx, "cpubench", "-j").Return(mockCmd).Times(4)
46+
t.Run("successful benchmark execution", func(t *testing.T) {
47+
48+
// Mock successful cpubench execution
49+
expectedOutput := `{
50+
"single": 1542.67,
51+
"multi": 6170.89,
52+
"threads": 4
53+
}`
54+
55+
data := make([]byte, 8)
56+
binary.LittleEndian.PutUint64(data, 5)
57+
response := &zbus.Response{
58+
ID: "test-id",
59+
Output: zbus.Output{
60+
Data: data,
61+
Error: nil,
62+
},
63+
}
64+
65+
mockZbus.EXPECT().
66+
RequestContext(gomock.Any(), "provision", zbus.ObjectID{Name: "statistics", Version: "0.0.1"}, "Workloads").
67+
Return(response, nil)
68+
69+
mockCmd.EXPECT().CombinedOutput().Return([]byte(expectedOutput), nil)
70+
71+
result, err := task.Run(ctx)
72+
require.NoError(t, err)
73+
assert.NotNil(t, result)
74+
75+
// Verify result structure
76+
cpuResult, ok := result.(CPUBenchmarkResult)
77+
require.True(t, ok, "Result should be of type CPUBenchmarkResult")
78+
79+
assert.Equal(t, 1542.67, cpuResult.SingleThreaded)
80+
assert.Equal(t, 6170.89, cpuResult.MultiThreaded)
81+
assert.Equal(t, 4, cpuResult.Threads)
82+
assert.Equal(t, 5, cpuResult.Workloads)
83+
84+
})
85+
86+
t.Run("cpubench command fails", func(t *testing.T) {
87+
// Mock command failure
88+
mockCmd.EXPECT().CombinedOutput().Return([]byte{}, errors.New("command not found"))
89+
90+
result, err := task.Run(ctx)
91+
assert.Error(t, err)
92+
assert.Nil(t, result)
93+
assert.Contains(t, err.Error(), "failed to execute cpubench command")
94+
})
95+
96+
t.Run("invalid JSON output", func(t *testing.T) {
97+
98+
// Mock command with invalid JSON output
99+
invalidJSON := `{invalid json output}`
100+
101+
mockCmd.EXPECT().CombinedOutput().Return([]byte(invalidJSON), nil)
102+
103+
result, err := task.Run(ctx)
104+
assert.Error(t, err)
105+
assert.Nil(t, result)
106+
assert.Contains(t, err.Error(), "failed to parse cpubench output")
107+
})
108+
109+
t.Run("failed to get workloads number", func(t *testing.T) {
110+
111+
mockCmd.EXPECT().CombinedOutput().Return([]byte(`{"single": 1000, "multi": 2000, "threads": 4}`), nil)
112+
// Mock failure in getting workloads number
113+
mockZbus.EXPECT().
114+
RequestContext(gomock.Any(), "provision", zbus.ObjectID{Name: "statistics", Version: "0.0.1"}, "Workloads").
115+
Return(nil, errors.New("failed to get workloads"))
116+
117+
assert.Panics(t, func() {
118+
_, _ = task.Run(ctx)
119+
})
120+
})
121+
}

0 commit comments

Comments
 (0)