• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16package rec
17
18import (
19	"context"
20	"crypto/md5"
21	"fmt"
22	"fotff/res"
23	"fotff/tester"
24	"github.com/sirupsen/logrus"
25	"math/rand"
26	"os"
27	"strconv"
28	"strings"
29	"sync"
30	"testing"
31	"time"
32)
33
34type FotffMocker struct {
35	FirstFail  int
36	steps      []string
37	lock       sync.Mutex
38	runningPkg map[string]string
39}
40
41func init() {
42	rand.Seed(time.Now().UnixNano())
43}
44
45func TestMain(m *testing.M) {
46	defer os.RemoveAll(".fotff")
47	defer os.RemoveAll("logs")
48	m.Run()
49}
50
51func NewFotffMocker(stepsNum int, firstFail int) *FotffMocker {
52	randomPrefix := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d", rand.Int()))))[:4]
53	steps := make([]string, stepsNum)
54	for i := 1; i <= stepsNum; i++ {
55		steps[i-1] = fmt.Sprintf("%s_%s", randomPrefix, strconv.Itoa(i))
56	}
57	return &FotffMocker{
58		FirstFail:  firstFail,
59		steps:      steps,
60		runningPkg: map[string]string{},
61	}
62}
63
64func (f *FotffMocker) TaskName() string {
65	return "mocker"
66}
67
68func (f *FotffMocker) Prepare(pkgDir string, device string, ctx context.Context) error {
69	return nil
70}
71
72func (f *FotffMocker) DoTestTask(device string, ctx context.Context) ([]tester.Result, error) {
73	time.Sleep(time.Duration(rand.Intn(1)) * time.Millisecond)
74	select {
75	case <-ctx.Done():
76		return nil, context.Canceled
77	default:
78	}
79	return []tester.Result{{TestCaseName: f.TestCaseName(), Status: tester.ResultFail}}, nil
80}
81
82func (f *FotffMocker) DoTestCase(device string, testcase string, ctx context.Context) (tester.Result, error) {
83	time.Sleep(time.Duration(rand.Intn(1)) * time.Millisecond)
84	select {
85	case <-ctx.Done():
86		return tester.Result{}, context.Canceled
87	default:
88	}
89	f.lock.Lock()
90	_, pkgPrefix, _ := strings.Cut(f.runningPkg[device], "_")
91	pkgOrder, _ := strconv.Atoi(pkgPrefix)
92	f.lock.Unlock()
93	if pkgOrder >= f.FirstFail {
94		logrus.Infof("mock: test %s at %s done, result is %s", testcase, device, tester.ResultFail)
95		return tester.Result{TestCaseName: testcase, Status: tester.ResultFail}, nil
96	}
97	logrus.Infof("mock: test %s at %s done, result is %s", testcase, device, tester.ResultPass)
98	return tester.Result{TestCaseName: testcase, Status: tester.ResultPass}, nil
99}
100
101func (f *FotffMocker) DoTestCases(device string, testcases []string, ctx context.Context) ([]tester.Result, error) {
102	var ret []tester.Result
103	for _, testcase := range testcases {
104		r, err := f.DoTestCase(device, testcase, ctx)
105		if err != nil {
106			return nil, err
107		}
108		ret = append(ret, r)
109	}
110	return ret, nil
111}
112
113func (f *FotffMocker) Flash(device string, pkg string, ctx context.Context) error {
114	time.Sleep(time.Duration(rand.Intn(1)) * time.Millisecond)
115	select {
116	case <-ctx.Done():
117		return context.Canceled
118	default:
119	}
120	f.lock.Lock()
121	f.runningPkg[device] = pkg
122	logrus.Infof("mock: flash %s to %s done", pkg, device)
123	f.lock.Unlock()
124	return nil
125}
126
127func (f *FotffMocker) LastIssue(pkg string) (string, error) {
128	return "issue" + pkg, nil
129}
130
131func (f *FotffMocker) Steps(from, to string) (ret []string, err error) {
132	return f.steps, nil
133}
134
135func (f *FotffMocker) GetNewer(cur string) (string, error) {
136	return "", nil
137}
138
139func (f *FotffMocker) PkgDir(pkg string) string {
140	return pkg
141}
142
143func (f *FotffMocker) TestCaseName() string {
144	return "MOCK_FAILED_TEST_CASE"
145}
146
147func (f *FotffMocker) Last() string {
148	return f.steps[len(f.steps)-1]
149}
150
151func TestFindOutTheFirstFail(t *testing.T) {
152	tests := []struct {
153		name   string
154		mocker *FotffMocker
155	}{
156		{
157			name:   "0-1(X)",
158			mocker: NewFotffMocker(1, 1),
159		},
160		{
161			name:   "0-1(X)-2",
162			mocker: NewFotffMocker(2, 1),
163		},
164		{
165			name:   "0-1-2(X)",
166			mocker: NewFotffMocker(2, 2),
167		},
168		{
169			name:   "0-1(X)-2-3",
170			mocker: NewFotffMocker(3, 1),
171		},
172		{
173			name:   "0-1-2(X)-3",
174			mocker: NewFotffMocker(3, 2),
175		},
176		{
177			name:   "0-1-2-3(X)",
178			mocker: NewFotffMocker(3, 3),
179		},
180		{
181			name:   "0-1(X)-2-3-4",
182			mocker: NewFotffMocker(4, 1),
183		},
184		{
185			name:   "0-1-2(X)-3-4",
186			mocker: NewFotffMocker(4, 2),
187		},
188		{
189			name:   "0-1-2-3(X)-4",
190			mocker: NewFotffMocker(4, 3),
191		},
192		{
193			name:   "0-1-2-3-4(X)",
194			mocker: NewFotffMocker(4, 4),
195		},
196		{
197			name:   "0-1(X)-2-3-4-5",
198			mocker: NewFotffMocker(5, 1),
199		},
200		{
201			name:   "0-1-2(X)-3-4-5",
202			mocker: NewFotffMocker(5, 2),
203		},
204		{
205			name:   "0-1-2-3(X)-4-5",
206			mocker: NewFotffMocker(5, 3),
207		},
208		{
209			name:   "0-1-2-3-4(X)-5",
210			mocker: NewFotffMocker(5, 4),
211		},
212		{
213			name:   "0-1-2-3-4-5(X)",
214			mocker: NewFotffMocker(5, 5),
215		},
216		{
217			name:   "0-1-2...262143(X)...1048575",
218			mocker: NewFotffMocker(1048575, 262143),
219		},
220		{
221			name:   "0-1-2...262144(X)...1048575",
222			mocker: NewFotffMocker(1048575, 262144),
223		},
224		{
225			name:   "0-1-2...262145(X)...1048575",
226			mocker: NewFotffMocker(1048575, 262145),
227		},
228		{
229			name:   "0-1-2...262143(X)...1048576",
230			mocker: NewFotffMocker(1048576, 262143),
231		},
232		{
233			name:   "0-1-2...262144(X)...1048576",
234			mocker: NewFotffMocker(1048576, 262144),
235		},
236		{
237			name:   "0-1-2...262145(X)...1048576",
238			mocker: NewFotffMocker(1048576, 262145),
239		},
240		{
241			name:   "0-1-2...262143(X)...1048577",
242			mocker: NewFotffMocker(1048577, 262143),
243		},
244		{
245			name:   "0-1-2...262144(X)...1048577",
246			mocker: NewFotffMocker(1048577, 262144),
247		},
248		{
249			name:   "0-1-2...262145(X)...1048577",
250			mocker: NewFotffMocker(1048577, 262145),
251		},
252		{
253			name:   "0-1-2...1234567(X)...10000000",
254			mocker: NewFotffMocker(10000000, 1234567),
255		},
256		{
257			name:   "0-1-2...1234567(X)...100000001",
258			mocker: NewFotffMocker(10000001, 1234567),
259		},
260		{
261			name:   "0-1-2...7654321(X)...10000000",
262			mocker: NewFotffMocker(10000000, 7654321),
263		},
264		{
265			name:   "0-1-2...7654321(X)...10000001",
266			mocker: NewFotffMocker(10000001, 7654321),
267		},
268		{
269			name:   "0-1(X)-2...10000000",
270			mocker: NewFotffMocker(10000000, 1),
271		},
272		{
273			name:   "0-1(X)-2...10000001",
274			mocker: NewFotffMocker(10000001, 1),
275		},
276		{
277			name:   "0-1-2...10000000(X)",
278			mocker: NewFotffMocker(10000000, 10000000),
279		},
280		{
281			name:   "0-1-2...10000001(X)",
282			mocker: NewFotffMocker(10000001, 10000001),
283		},
284	}
285	for i := 1; i <= 5; i++ {
286		res.Fake(i)
287		for _, tt := range tests {
288			t.Run(fmt.Sprintf("RES%d:%s", i, tt.name), func(t *testing.T) {
289				ret, err := FindOutTheFirstFail(tt.mocker, tt.mocker, tt.mocker.TestCaseName(), "0", tt.mocker.Last())
290				if err != nil {
291					t.Errorf("err: expcect: <nil>, actual: %v", err)
292				}
293				expectIssue, _ := tt.mocker.LastIssue(tt.mocker.steps[tt.mocker.FirstFail-1])
294				if ret != expectIssue {
295					t.Errorf("fotff result: expect: %s, actual: %s", expectIssue, ret)
296				}
297			})
298		}
299	}
300}
301