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 xdevice 17 18import ( 19 "context" 20 "crypto/md5" 21 "encoding/xml" 22 "errors" 23 "fmt" 24 "fotff/tester" 25 "fotff/utils" 26 "github.com/sirupsen/logrus" 27 "math/rand" 28 "os" 29 "path/filepath" 30 "strings" 31 "time" 32) 33 34const enableTestModeScript = `mount -o rw,remount /; param set persist.ace.testmode.enabled 1; param set persist.sys.hilog.debug.on true; sed -i 's/enforcing/permissive/g' /system/etc/selinux/config; sync; reboot` 35 36type Tester struct { 37 Task string `key:"task" default:"acts"` 38 Config string `key:"config" default:"./config/user_config.xml"` 39 TestCasesPath string `key:"test_cases_path" default:"./testcases"` 40 ResourcePath string `key:"resource_path" default:"./resource"` 41} 42 43type Report struct { 44 XMLName xml.Name `xml:"testsuites"` 45 TestSuite []struct { 46 TestCase []struct { 47 Name string `xml:"name,attr"` 48 Result string `xml:"result,attr"` 49 } `xml:"testcase"` 50 } `xml:"testsuite"` 51} 52 53func init() { 54 rand.Seed(time.Now().UnixNano()) 55} 56 57func NewTester() tester.Tester { 58 ret := &Tester{} 59 utils.ParseFromConfigFile("xdevice", ret) 60 return ret 61} 62 63func (t *Tester) TaskName() string { 64 return t.Task 65} 66 67func (t *Tester) Prepare(pkgDir string, device string, ctx context.Context) (err error) { 68 logrus.Info("for xdevice test, try to enable test mode...") 69 if err := utils.HdcShell(enableTestModeScript, device, ctx); err != nil { 70 return err 71 } 72 time.Sleep(20 * time.Second) // usually, it takes about 20s to reboot into OpenHarmony 73 if connected := utils.WaitHDC(device, ctx); !connected { 74 logrus.Errorf("enable test mode at device %s done, but boot unnormally, hdc connection fail", device) 75 return fmt.Errorf("enable test mode at device %s done, but boot unnormally, hdc connection fail", device) 76 } 77 time.Sleep(10 * time.Second) // wait 10s more to ensure system has been started completely 78 logrus.Infof("enable test mode at device %s successfully", device) 79 return nil 80} 81 82func (t *Tester) DoTestTask(deviceSN string, ctx context.Context) (ret []tester.Result, err error) { 83 reportDir := fmt.Sprintf("%X", md5.Sum([]byte(fmt.Sprintf("%d", rand.Int())))) 84 args := []string{"-m", "xdevice", "run", t.Task, "-c", t.Config, "-tcpath", t.TestCasesPath, "-respath", t.ResourcePath, "-rp", reportDir} 85 if deviceSN != "" { 86 args = append(args, "-sn", deviceSN) 87 } 88 if err := utils.ExecContext(ctx, "python", args...); err != nil { 89 if errors.Is(err, context.Canceled) { 90 return nil, err 91 } 92 logrus.Errorf("do test suite fail: %v", err) 93 return nil, err 94 } 95 return t.readReport(reportDir) 96} 97 98func (t *Tester) DoTestCase(deviceSN, testCase string, ctx context.Context) (ret tester.Result, err error) { 99 reportDir := fmt.Sprintf("%X", md5.Sum([]byte(fmt.Sprintf("%d", rand.Int())))) 100 args := []string{"-m", "xdevice", "run", "-l", testCase, "-c", t.Config, "-tcpath", t.TestCasesPath, "-respath", t.ResourcePath, "-rp", reportDir} 101 if deviceSN != "" { 102 args = append(args, "-sn", deviceSN) 103 } 104 if err := utils.ExecContext(ctx, "python", args...); err != nil { 105 if errors.Is(err, context.Canceled) { 106 return ret, err 107 } 108 logrus.Errorf("do test case %s fail: %v", testCase, err) 109 return ret, err 110 } 111 r, err := t.readReport(reportDir) 112 if len(r) == 0 { 113 return ret, fmt.Errorf("read latest report err, no result found") 114 } 115 if r[0].TestCaseName != testCase { 116 return ret, fmt.Errorf("read latest report err, no matched result found") 117 } 118 logrus.Infof("do testcase %s at %s done, result is %s", r[0].TestCaseName, deviceSN, r[0].Status) 119 return r[0], nil 120} 121 122func (t *Tester) DoTestCases(deviceSN string, testcases []string, ctx context.Context) (ret []tester.Result, err error) { 123 reportDir := fmt.Sprintf("%X", md5.Sum([]byte(fmt.Sprintf("%d", rand.Int())))) 124 args := []string{"-m", "xdevice", "run", "-l", strings.Join(testcases, ";"), "-c", t.Config, "-tcpath", t.TestCasesPath, "-respath", t.ResourcePath, "-rp", reportDir} 125 if deviceSN != "" { 126 args = append(args, "-sn", deviceSN) 127 } 128 if err := utils.ExecContext(ctx, "python", args...); err != nil { 129 if errors.Is(err, context.Canceled) { 130 return ret, err 131 } 132 logrus.Errorf("do test cases %v fail: %v", testcases, err) 133 return ret, err 134 } 135 return t.readReport(reportDir) 136} 137 138func (t *Tester) readReport(reportDir string) (ret []tester.Result, err error) { 139 data, err := os.ReadFile(filepath.Join("reports", reportDir, "summary_report.xml")) 140 if err != nil { 141 logrus.Errorf("read report xml fail: %v", err) 142 return nil, err 143 } 144 var report Report 145 err = xml.Unmarshal(data, &report) 146 if err != nil { 147 logrus.Errorf("unmarshal report xml fail: %v", err) 148 return nil, err 149 } 150 for _, s := range report.TestSuite { 151 for _, c := range s.TestCase { 152 var status tester.ResultStatus 153 if c.Result == "true" { 154 status = tester.ResultPass 155 } else { 156 status = tester.ResultFail 157 } 158 ret = append(ret, tester.Result{TestCaseName: c.Name, Status: status}) 159 } 160 } 161 return ret, err 162} 163