// Copyright 2019 Mikhail Klementev. All rights reserved. // Use of this source code is governed by a AGPLv3 license // (or later) that can be found in the LICENSE file. package main import ( "database/sql" "encoding/json" "fmt" "log" "math" "os" "github.com/olekukonko/tablewriter" "gopkg.in/logrusorgru/aurora.v1" "code.dumpstack.io/tools/out-of-tree/config" ) func logLogEntry(l logEntry) { distroInfo := fmt.Sprintf("%s-%s {%s}", l.DistroType, l.DistroRelease, l.KernelRelease) artifactInfo := fmt.Sprintf("{[%s] %s}", l.Type, l.Name) colored := "" if l.Type == config.KernelExploit { colored = aurora.Sprintf("[%4d %4s] [%s] %40s %40s: %s %s", l.ID, l.Tag, l.Timestamp, artifactInfo, distroInfo, genOkFail("BUILD", l.Build.Ok), genOkFail("LPE", l.Test.Ok)) } else { colored = aurora.Sprintf("[%4d %4s] [%s] %40s %40s: %s %s %s", l.ID, l.Tag, l.Timestamp, artifactInfo, distroInfo, genOkFail("BUILD", l.Build.Ok), genOkFail("INSMOD", l.Run.Ok), genOkFail("TEST", l.Test.Ok)) } additional := "" if l.KernelPanic { additional = "(panic)" } else if l.KilledByTimeout { additional = "(timeout)" } if additional != "" { fmt.Println(colored, additional) } else { fmt.Println(colored) } } func logHandler(db *sql.DB, path, tag string, num int, rate bool) (err error) { var les []logEntry ka, kaErr := config.ReadArtifactConfig(path + "/.out-of-tree.toml") if kaErr == nil { log.Println(".out-of-tree.toml found, filter by artifact name") les, err = getAllArtifactLogs(db, tag, num, ka) } else { les, err = getAllLogs(db, tag, num) } if err != nil { return } s := "\nS" if rate { if kaErr != nil { err = kaErr return } s = fmt.Sprintf("{[%s] %s} Overall s", ka.Type, ka.Name) les, err = getAllArtifactLogs(db, tag, math.MaxInt64, ka) if err != nil { return } } else { for _, l := range les { logLogEntry(l) } } success := 0 for _, l := range les { if l.Test.Ok { success++ } } overall := float64(success) / float64(len(les)) fmt.Printf("%success rate: %.04f (~%.0f%%)\n", s, overall, overall*100) return } func logDumpHandler(db *sql.DB, id int) (err error) { l, err := getLogByID(db, id) if err != nil { return } fmt.Println("ID:", l.ID) fmt.Println("Date:", l.Timestamp) fmt.Println("Tag:", l.Tag) fmt.Println() fmt.Println("Type:", l.Type.String()) fmt.Println("Name:", l.Name) fmt.Println() fmt.Println("Distro:", l.DistroType.String(), l.DistroRelease) fmt.Println("Kernel:", l.KernelRelease) fmt.Println() fmt.Println("Build ok:", l.Build.Ok) if l.Type == config.KernelModule { fmt.Println("Insmod ok:", l.Run.Ok) } fmt.Println("Test ok:", l.Test.Ok) fmt.Println() fmt.Printf("Build output:\n%s\n", l.Build.Output) fmt.Println() if l.Type == config.KernelModule { fmt.Printf("Insmod output:\n%s\n", l.Run.Output) fmt.Println() } fmt.Printf("Test output:\n%s\n", l.Test.Output) fmt.Println() fmt.Printf("Qemu stdout:\n%s\n", l.Stdout) fmt.Println() fmt.Printf("Qemu stderr:\n%s\n", l.Stderr) fmt.Println() return } type runstat struct { All, BuildOK, RunOK, TestOK, Timeout, Panic int } func getStats(db *sql.DB, path, tag string) ( distros map[string]map[string]map[string]runstat, err error) { var les []logEntry ka, kaErr := config.ReadArtifactConfig(path + "/.out-of-tree.toml") if kaErr == nil { les, err = getAllArtifactLogs(db, tag, -1, ka) } else { les, err = getAllLogs(db, tag, -1) } if err != nil { return } distros = make(map[string]map[string]map[string]runstat) for _, l := range les { _, ok := distros[l.DistroType.String()] if !ok { distros[l.DistroType.String()] = make(map[string]map[string]runstat) } _, ok = distros[l.DistroType.String()][l.DistroRelease] if !ok { distros[l.DistroType.String()][l.DistroRelease] = make(map[string]runstat) } rs := distros[l.DistroType.String()][l.DistroRelease][l.KernelRelease] rs.All++ if l.Build.Ok { rs.BuildOK++ } if l.Run.Ok { rs.RunOK++ } if l.Test.Ok { rs.TestOK++ } if l.KernelPanic { rs.Panic++ } if l.KilledByTimeout { rs.Timeout++ } distros[l.DistroType.String()][l.DistroRelease][l.KernelRelease] = rs } return } func logJSONHandler(db *sql.DB, path, tag string) (err error) { distros, err := getStats(db, path, tag) if err != nil { return } bytes, err := json.Marshal(&distros) if err != nil { return } fmt.Println(string(bytes)) return } func logMarkdownHandler(db *sql.DB, path, tag string) (err error) { distros, err := getStats(db, path, tag) if err != nil { return } table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Distro", "Release", "Kernel", "Reliability"}) table.SetBorders(tablewriter.Border{ Left: true, Top: false, Right: true, Bottom: false}) table.SetCenterSeparator("|") for distro, releases := range distros { for release, kernels := range releases { for kernel, stats := range kernels { all := float64(stats.All) ok := float64(stats.TestOK) r := fmt.Sprintf("%6.02f%%", (ok/all)*100) table.Append([]string{distro, release, kernel, r}) } } } table.Render() return }