a4c84f3d创建于 2023年4月20日历史提交
/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"context"
	"fotff/pkg"
	"fotff/pkg/dayu200"
	"fotff/pkg/gitee_build"
	"fotff/pkg/mock"
	"fotff/rec"
	"fotff/res"
	"fotff/tester"
	"fotff/tester/common"
	"fotff/tester/manual"
	testermock "fotff/tester/mock"
	"fotff/tester/pkg_available"
	"fotff/tester/smoke"
	"fotff/tester/xdevice"
	"fotff/utils"
	"os"
	"path/filepath"

	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

var newPkgMgrFuncs = map[string]pkg.NewFunc{
	"mock":        mock.NewManager,
	"dayu200":     dayu200.NewManager,
	"gitee_build": gitee_build.NewManager,
}

var newTesterFuncs = map[string]tester.NewFunc{
	"mock":          testermock.NewTester,
	"manual":        manual.NewTester,
	"common":        common.NewTester,
	"xdevice":       xdevice.NewTester,
	"smoke":         smoke.NewTester,
	"pkg_available": pkg_available.NewTester,
}

var rootCmd *cobra.Command

func init() {
	m, t := initExecutor()
	rootCmd = &cobra.Command{
		Run: func(cmd *cobra.Command, args []string) {
			loop(m, t)
		},
	}
	runCmd := initRunCmd(m, t)
	flashCmd := initFlashCmd(m)
	testCmd := initTestCmd(m, t)
	rootCmd.AddCommand(runCmd, flashCmd, testCmd)
}

func initRunCmd(m pkg.Manager, t tester.Tester) *cobra.Command {
	var success, fail, testcase string
	runCmd := &cobra.Command{
		Use:   "run",
		Short: "bin-search in (success, fail] by do given testcase to find out the fist fail, and print the corresponding issue",
		RunE: func(cmd *cobra.Command, args []string) error {
			return fotff(m, t, success, fail, testcase)
		},
	}
	runCmd.PersistentFlags().StringVarP(&success, "success", "s", "", "success package directory")
	runCmd.PersistentFlags().StringVarP(&fail, "fail", "f", "", "fail package directory")
	runCmd.PersistentFlags().StringVarP(&testcase, "testcase", "t", "", "testcase name")
	runCmd.MarkPersistentFlagRequired("success")
	runCmd.MarkPersistentFlagRequired("fail")
	runCmd.MarkPersistentFlagRequired("testcase")
	return runCmd
}

func initFlashCmd(m pkg.Manager) *cobra.Command {
	var flashPkg, device string
	flashCmd := &cobra.Command{
		Use:   "flash",
		Short: "flash the given package",
		RunE: func(cmd *cobra.Command, args []string) error {
			return m.Flash(device, flashPkg, context.TODO())
		},
	}
	flashCmd.PersistentFlags().StringVarP(&flashPkg, "package", "p", "", "package directory")
	flashCmd.PersistentFlags().StringVarP(&device, "device", "d", "", "device sn")
	flashCmd.MarkPersistentFlagRequired("package")
	return flashCmd
}

func initTestCmd(m pkg.Manager, t tester.Tester) *cobra.Command {
	var targetPkg, device, testCase string
	testCmd := &cobra.Command{
		Use:   "test",
		Short: "build and flash and test the given package on the specified device",
		RunE: func(cmd *cobra.Command, args []string) error {
			opt := &rec.FlashAndTestOptions{
				M:        m,
				T:        t,
				Version:  targetPkg,
				Device:   device,
				TestCase: testCase,
			}
			return rec.FlashAndTest(context.TODO(), opt)
		},
	}
	testCmd.PersistentFlags().StringVarP(&targetPkg, "package", "p", "", "package directory")
	testCmd.PersistentFlags().StringVarP(&device, "device", "d", "", "target device sn")
	testCmd.PersistentFlags().StringVarP(&testCase, "testcase", "t", "", "test case to run")
	testCmd.MarkPersistentFlagRequired("package")
	testCmd.MarkPersistentFlagRequired("device")

	return testCmd
}

func main() {
	utils.EnablePprof()
	if err := rootCmd.Execute(); err != nil {
		logrus.Errorf("failed to execute: %v", err)
		os.Exit(1)
	}
}

func loop(m pkg.Manager, t tester.Tester) {
	data, _ := utils.ReadRuntimeData("last_handled.rec")
	var curPkg = string(data)
	for {
		utils.ResetLogOutput()
		if err := utils.WriteRuntimeData("last_handled.rec", []byte(curPkg)); err != nil {
			logrus.Errorf("failed to write last_handled.rec: %v", err)
		}
		logrus.Info("waiting for a newer package...")
		var err error
		curPkg, err = m.GetNewer(curPkg)
		if err != nil {
			logrus.Infof("get newer package err: %v", err)
			continue
		}
		utils.SetLogOutput(filepath.Base(curPkg))
		logrus.Infof("now flash %s...", curPkg)
		device := res.GetDevice()
		if err := m.Flash(device, curPkg, context.TODO()); err != nil {
			logrus.Errorf("flash package dir %s err: %v", curPkg, err)
			res.ReleaseDevice(device)
			continue
		}
		if err := t.Prepare(m.PkgDir(curPkg), device, context.TODO()); err != nil {
			logrus.Errorf("do test preperation for package %s err: %v", curPkg, err)
			continue
		}
		logrus.Info("now do test suite...")
		results, err := t.DoTestTask(device, context.TODO())
		if err != nil {
			logrus.Errorf("do test suite for package %s err: %v", curPkg, err)
			continue
		}
		for _, r := range results {
			logrus.Infof("do test case %s at %s done, result is %v", r.TestCaseName, device, r.Status)
		}
		logrus.Infof("now analysis test results...")
		toFotff := rec.HandleResults(t, device, curPkg, results)
		res.ReleaseDevice(device)
		rec.Analysis(m, t, curPkg, toFotff)
		rec.Save()
		rec.Report(curPkg, t.TaskName())
	}
}

func fotff(m pkg.Manager, t tester.Tester, success, fail, testcase string) error {
	issueURL, err := rec.FindOutTheFirstFail(m, t, testcase, success, fail)
	if err != nil {
		logrus.Errorf("failed to find out the first fail: %v", err)
		return err
	}
	logrus.Infof("the first fail found: %v", issueURL)
	return nil
}

func initExecutor() (pkg.Manager, tester.Tester) {
	//TODO load from config file
	var conf = struct {
		PkgManager string `key:"pkg_manager" default:"mock"`
		Tester     string `key:"tester" default:"mock"`
	}{}
	utils.ParseFromConfigFile("", &conf)
	newPkgMgrFunc, ok := newPkgMgrFuncs[conf.PkgManager]
	if !ok {
		logrus.Panicf("no package manager found for %s", conf.PkgManager)
	}
	newTesterFunc, ok := newTesterFuncs[conf.Tester]
	if !ok {
		logrus.Panicf("no tester found for %s", conf.Tester)
	}
	return newPkgMgrFunc(), newTesterFunc()
}