github.com/koko1123/flow-go-1@v0.29.6/tools/test_monitor/level2/process_summary2_results_test.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/koko1123/flow-go-1/tools/test_monitor/common"
    12  	"github.com/koko1123/flow-go-1/tools/test_monitor/common/testdata"
    13  	"github.com/koko1123/flow-go-1/utils/unittest"
    14  )
    15  
    16  func TestGenerateLevel2Summary_Struct(t *testing.T) {
    17  	testDataMap := map[string]testdata.Level2TestData{
    18  		"1 level 1 summary, 1 failure the rest pass": {
    19  			Directory:       "test1-1package-1failure",
    20  			HasFailures:     true,
    21  			HasExceptions:   false,
    22  			Level1Summaries: testdata.GetTestData_Level2_1FailureRestPass(),
    23  		},
    24  
    25  		"1 level 1 summary, 1 exception, no other tests": {
    26  			Directory:       "test2-1-exception",
    27  			HasFailures:     false,
    28  			HasExceptions:   true,
    29  			Level1Summaries: testdata.GetTestsData_Level2_1ExceptionNoOtherTests(),
    30  		},
    31  
    32  		"many level 1 summaries, many exceptions": {
    33  			Directory:       "test3-multi-exceptions",
    34  			HasFailures:     false,
    35  			HasExceptions:   true,
    36  			Level1Summaries: testdata.GetTestData_Level2_MultipleL1SummariesExceptions(),
    37  		},
    38  
    39  		"many level 1 summaries, many failures, many passes": {
    40  			Directory:       "test4-multi-failures",
    41  			HasFailures:     true,
    42  			HasExceptions:   false,
    43  			Level1Summaries: testdata.GetTestData_Level2MultipleL1SummariesFailuresPasses(),
    44  		},
    45  
    46  		"many level 1 summaries, many failures, many passes, many exceptions": {
    47  			Directory:       "test5-multi-failures-multi-exceptions",
    48  			HasFailures:     true,
    49  			HasExceptions:   true,
    50  			Level1Summaries: testdata.GetTestData_Level2MultipleL1SummariesFailuresPassesExceptions(),
    51  		},
    52  	}
    53  
    54  	for k, testData := range testDataMap {
    55  		t.Run(k, func(t *testing.T) {
    56  			setUp(t)
    57  			// ************************
    58  			actualLevel2Summary := generateLevel2SummaryFromStructs(testData.Level1Summaries)
    59  			// ************************
    60  			checkLevel2Summary(t, actualLevel2Summary, testData)
    61  			tearDown(t)
    62  		})
    63  	}
    64  }
    65  
    66  // TestGenerateLevel2Summary_JSON uses real level 1 JSON files as input
    67  // Don't want to use too many tests since they are more brittle to changes to JSON data structure.
    68  // That's why have very few of these. For new tests, it's best to add level 1 data as structs.
    69  func TestGenerateLevel2Summary_JSON(t *testing.T) {
    70  	unittest.SkipUnless(t, unittest.TEST_TODO, "broken")
    71  	testDataMap := map[string]testdata.Level2TestData{
    72  		"1 level 1 summary, 1 failure the rest pass": {
    73  			Directory:      "test1-1package-1failure",
    74  			Level1DataPath: "../testdata/summary2/test1-1package-1failure/input",
    75  			HasFailures:    true,
    76  			HasExceptions:  false,
    77  		},
    78  	}
    79  	for k, testData := range testDataMap {
    80  		t.Run(k, func(t *testing.T) {
    81  			setUp(t)
    82  			// ************************
    83  			actualLevel2Summary := generateLevel2Summary(testData.Level1DataPath)
    84  			// ************************
    85  			checkLevel2Summary(t, actualLevel2Summary, testData)
    86  			tearDown(t)
    87  		})
    88  	}
    89  }
    90  
    91  func setUp(t *testing.T) {
    92  	deleteMessagesDir(t)
    93  }
    94  
    95  func tearDown(t *testing.T) {
    96  	deleteMessagesDir(t)
    97  }
    98  
    99  // HELPERS - UTILITIES
   100  
   101  const actualFailureMessagesPath = "./failures"
   102  const actualExceptionMessagesPath = "./exceptions"
   103  
   104  func deleteMessagesDir(t *testing.T) {
   105  	// delete failure test dir that stores failure messages
   106  	err := os.RemoveAll(actualFailureMessagesPath)
   107  	require.Nil(t, err)
   108  
   109  	// delete exceptions test dir that stores exception messages
   110  	err = os.RemoveAll(actualExceptionMessagesPath)
   111  	require.Nil(t, err)
   112  }
   113  
   114  func checkLevel2Summary(t *testing.T, actualLevel2Summary common.Level2Summary, testData testdata.Level2TestData) {
   115  	expectedOutputTestDataPath := filepath.Join("../testdata/summary2", testData.Directory, "expected-output", testData.Directory+".json")
   116  	expectedFailureMessagesPath := filepath.Join("../testdata/summary2", testData.Directory, "expected-output/failures")
   117  	expectedExceptionMessagesPath := filepath.Join("../testdata/summary2", testData.Directory, "expected-output/exceptions")
   118  
   119  	// read in expected summary level 2
   120  	var expectedLevel2Summary common.Level2Summary
   121  	expectedLevel2SummaryJsonBytes, err := os.ReadFile(expectedOutputTestDataPath)
   122  	require.Nil(t, err)
   123  	require.NotEmpty(t, expectedLevel2SummaryJsonBytes)
   124  	err = json.Unmarshal(expectedLevel2SummaryJsonBytes, &expectedLevel2Summary)
   125  	require.Nil(t, err)
   126  
   127  	require.Equal(t, len(expectedLevel2Summary.TestResultsMap), len(actualLevel2Summary.TestResultsMap))
   128  
   129  	// check every expected test runs level 2 summary exists in map of actual test runs level 2 summaries
   130  	for expectedLevel2TestResultKey := range expectedLevel2Summary.TestResultsMap {
   131  		expectedLevel2TestResult := expectedLevel2Summary.TestResultsMap[expectedLevel2TestResultKey]
   132  		actualLevel2TestResults, isFoundActual := actualLevel2Summary.TestResultsMap[expectedLevel2TestResultKey]
   133  
   134  		require.True(t, isFoundActual, common.PrintLevel2TestResult(expectedLevel2TestResult, "expected not in actual"))
   135  
   136  		common.AssertLevel2TestResults(t, *expectedLevel2TestResult, *actualLevel2TestResults)
   137  	}
   138  
   139  	// check every actual test runs level 2 summary exists in map of expected test runs level 2 summaries
   140  	for actualLevel2TestResultKey := range actualLevel2Summary.TestResultsMap {
   141  		actualLevel2TestResult := actualLevel2Summary.TestResultsMap[actualLevel2TestResultKey]
   142  		exptectedLevel2TestResult, isFoundExpected := expectedLevel2Summary.TestResultsMap[actualLevel2TestResultKey]
   143  
   144  		require.True(t, isFoundExpected, common.PrintLevel2TestResult(actualLevel2TestResult, "actual not in expected"))
   145  
   146  		common.AssertLevel2TestResults(t, *exptectedLevel2TestResult, *actualLevel2TestResult)
   147  	}
   148  
   149  	checkFailureMessages(t, testData.HasFailures, expectedFailureMessagesPath)
   150  	checkExceptionMessages(t, testData.HasExceptions, expectedExceptionMessagesPath)
   151  }
   152  
   153  // check failure messages created
   154  // there are 2 types of scenarios:
   155  //  1. test summaries with no failures - these will not have a `failures` sub-directory and no more checking is needed
   156  //  2. test summaries with failures - these will have a `failures` sub-directory with failure messages saved
   157  //     in text files (1 file/failure under separate sub-directory for each test that has failures)
   158  func checkFailureMessages(t *testing.T, hasFailures bool, expectedFailureMessagesPath string) {
   159  	if !hasFailures {
   160  		return
   161  	}
   162  	checkMessagesHelper(t, expectedFailureMessagesPath, actualFailureMessagesPath)
   163  }
   164  
   165  // check exception messages created - for tests that generated no pass / fail
   166  // there are 2 types of scenarios:
   167  //  1. test summaries with no "exception" - these will not have an `exception` sub-directory and no more checking is needed
   168  //  2. test summaries with exceptions - these will have an `exception` sub-directory with output messages saved
   169  //     in text files (1 file/exception under separate sub-directory for each test that has exceptions)
   170  func checkExceptionMessages(t *testing.T, HasExceptions bool, expectedExceptionMessagesPath string) {
   171  	if !HasExceptions {
   172  		return
   173  	}
   174  	checkMessagesHelper(t, expectedExceptionMessagesPath, actualExceptionMessagesPath)
   175  }
   176  
   177  // helps check for both failures and exception messages since they are very similar, just under
   178  // different directories
   179  func checkMessagesHelper(t *testing.T, expectedMessagesPath string, actualMessagesPath string) {
   180  
   181  	// count expected failure / exception directories (1 directory/test)
   182  	expectedMessageDirs, err := os.ReadDir(expectedMessagesPath)
   183  	require.Nil(t, err)
   184  
   185  	// count actual failure / exception directories
   186  	actualMessageDirs, err := os.ReadDir(actualMessagesPath)
   187  	require.Nil(t, err)
   188  
   189  	// expected test summary has at least 1 failure / exception
   190  	require.Equal(t, len(expectedMessageDirs), len(actualMessageDirs))
   191  
   192  	// compare expected vs actual messages
   193  	for expectedMessageDirIndex, expectedMessageDir := range expectedMessageDirs {
   194  
   195  		// sub-directory names should be the same - each sub directory corresponds to a failed / exception test name
   196  		require.Equal(t, expectedMessageDir.Name(), actualMessageDirs[expectedMessageDirIndex].Name())
   197  
   198  		// under each sub-directory, there should be 1 or more text files (failure1.txt/exception1.txt, failure2.txt/exception2.txt, etc)
   199  		// that holds the raw failure / exception message for that test
   200  		expectedMessagesDirFiles, err := os.ReadDir(filepath.Join(expectedMessagesPath, expectedMessageDir.Name()))
   201  		require.Nil(t, err)
   202  
   203  		actualMessageDirFiles, err := os.ReadDir(filepath.Join(actualMessagesPath, actualMessageDirs[expectedMessageDirIndex].Name()))
   204  		require.Nil(t, err)
   205  
   206  		// make sure there are the expected number of failed / exception text files in the sub-directory
   207  		require.Equal(t, len(expectedMessagesDirFiles), len(actualMessageDirFiles))
   208  
   209  		// check contents of each text file for expected failure / exception message
   210  		// for every test that has failures / exception, there should be 1 text file per failure / exception
   211  
   212  		// if test has failures / exceptions, there should be directory of failure / exception messages text files
   213  		// a sub-directory of the test name will hold all test failure / exception messages
   214  
   215  		for expectedMessageFileIndex, expectedMessageFileDirEntry := range expectedMessagesDirFiles {
   216  			expectedMessageFilePath := filepath.Join(expectedMessagesPath, expectedMessageDir.Name(), expectedMessageFileDirEntry.Name())
   217  			expectedMessageFileBytes, err := os.ReadFile(expectedMessageFilePath)
   218  			require.Nil(t, err)
   219  
   220  			actualMessageFilePath := filepath.Join(actualMessagesPath, actualMessageDirs[expectedMessageDirIndex].Name(), actualMessageDirFiles[expectedMessageFileIndex].Name())
   221  			actualMessageFileBytes, err := os.ReadFile(actualMessageFilePath)
   222  			require.Nil(t, err)
   223  
   224  			// read expected and actual text files as bytes and compare them all at once
   225  			require.Equal(t, expectedMessageFileBytes, actualMessageFileBytes)
   226  		}
   227  	}
   228  }