github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/tools/test_monitor/level3/process_summary3_results.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"sort"
     7  
     8  	"github.com/onflow/flow-go/tools/test_monitor/common"
     9  )
    10  
    11  // generateLevel3Summary processes a level 2 summary and produces level 3 summary which summarizes:
    12  // most failed tests, tests with exceptions, longest running tests.
    13  func generateLevel3Summary(level2FilePath string, propertyFileDirectory string) common.Level3Summary {
    14  
    15  	config := common.ReadProperties(propertyFileDirectory)
    16  
    17  	var level2Summary common.Level2Summary
    18  
    19  	level2JsonBytes, err := os.ReadFile(level2FilePath)
    20  	common.AssertNoError(err, "error reading level 2 json")
    21  
    22  	err = json.Unmarshal(level2JsonBytes, &level2Summary)
    23  	common.AssertNoError(err, "error unmarshalling level 2 test run")
    24  
    25  	// there should be at least 1 level 2 test result in the supplied file
    26  	// if the json format is different in the supplied file, there won't be a marshalling error thrown
    27  	// this is an indirect way to tell if the json format was wrong (i.e. not a level 2 json format)
    28  	if len(level2Summary.TestResultsMap) == 0 {
    29  		panic("invalid summary 2 file - no test results found")
    30  	}
    31  
    32  	// create lists to keep track of 3 main things
    33  	// 1. tests with exceptions (ordered by most exceptions)
    34  	// 2. tests with failures (ordered by most failures)
    35  	// 3. tests with durations > 0 (ordered by longest durations)
    36  
    37  	exceptionsTRS := []common.Level2TestResult{}
    38  	failuresTRS := []common.Level2TestResult{}
    39  	durationTRS := []common.Level2TestResult{}
    40  
    41  	// go through all level 2 test results to figure out grouping for tests with
    42  	// most failures, exceptions, longest running
    43  	for _, trs := range level2Summary.TestResultsMap {
    44  		if trs.Exceptions > 0 {
    45  			exceptionsTRS = append(exceptionsTRS, *trs)
    46  		}
    47  		if trs.Failed > 0 && trs.FailureRate >= config.FailureThresholdPercent {
    48  			failuresTRS = append(failuresTRS, *trs)
    49  		}
    50  		if trs.AverageDuration > 0 && trs.AverageDuration >= config.DurationThresholdSeconds {
    51  			durationTRS = append(durationTRS, *trs)
    52  		}
    53  	}
    54  
    55  	// sort no result slice from most no results to least - that's why less function compares in reverse order
    56  	sort.Slice(exceptionsTRS, func(i, j int) bool {
    57  		return (exceptionsTRS[i].Exceptions > exceptionsTRS[j].Exceptions)
    58  	})
    59  
    60  	// sort failures slice from most failures to least - that's why less function compares in reverse order
    61  	sort.Slice(failuresTRS, func(i, j int) bool {
    62  		return failuresTRS[i].FailureRate > failuresTRS[j].FailureRate
    63  	})
    64  
    65  	// sort duration slice from longest duration to shortest - that's why less function compares in reverse order
    66  	sort.Slice(durationTRS, func(i, j int) bool {
    67  		return durationTRS[i].AverageDuration > durationTRS[j].AverageDuration
    68  	})
    69  
    70  	var level3Summary common.Level3Summary
    71  	level3Summary.Exceptions = exceptionsTRS
    72  
    73  	// total # of failed tests that satisfy min failure threshold
    74  	level3Summary.MostFailuresTotal = len(failuresTRS)
    75  
    76  	// check if # of failures exceeded max failures to return
    77  	if len(failuresTRS) > config.FailuresSliceMax {
    78  		// truncate slice to return only the first config.FailuresSliceMax failures
    79  		failuresTRS = failuresTRS[:config.FailuresSliceMax]
    80  	}
    81  	level3Summary.MostFailures = failuresTRS
    82  
    83  	// total # of long tests that satisfy min duration threshold
    84  	level3Summary.LongestRunningTotal = len(durationTRS)
    85  
    86  	// check if # of durations exceeded max durations to return
    87  	if len(durationTRS) > config.DurationSliceMax {
    88  		// truncate slice to return only the first config.DurationSliceMax durations
    89  		durationTRS = durationTRS[:config.DurationSliceMax]
    90  	}
    91  	level3Summary.LongestRunning = durationTRS
    92  
    93  	return level3Summary
    94  }
    95  
    96  func main() {
    97  	// need to pass in single argument of where level 1 summary files exist
    98  	if len(os.Args[1:]) != 2 {
    99  		panic("wrong number of arguments - expected arguments 1) path of level 2 file 2) directory of property file")
   100  	}
   101  
   102  	level3Summary := generateLevel3Summary(os.Args[1], os.Args[2])
   103  	common.SaveToFile("level3-summary.json", level3Summary)
   104  }