Skip to content

Commit

Permalink
Merge branch 'main' into 166_single_groupElement
Browse files Browse the repository at this point in the history
  • Loading branch information
ShiriMoran authored Nov 1, 2023
2 parents c5e5071 + 4dd05e2 commit fccb150
Show file tree
Hide file tree
Showing 15 changed files with 12,481 additions and 108 deletions.
42 changes: 28 additions & 14 deletions cmd/analyzer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,27 @@ func analysisTypeToUseCase(inArgs *InArgs) vpcmodel.OutputUseCase {
return vpcmodel.AllEndpoints
}

func analysisPerVPCConfig(c *vpcmodel.VPCConfig, inArgs *InArgs) error {
func analysisPerVPCConfig(c *vpcmodel.VPCConfig, inArgs *InArgs, outFile string) (*vpcmodel.VPCAnalysisOutput, error) {
og, err := vpcmodel.NewOutputGenerator(c,
*inArgs.Grouping,
analysisTypeToUseCase(inArgs),
*inArgs.OutputFormat == ARCHDRAWIOFormat)
if err != nil {
return err
return nil, err
}
outFile := ""
if inArgs.OutputFile != nil {
outFile = *inArgs.OutputFile

var genOutFile string
// currently for drawio output only one vpc level is supported, and not as aggregated output of multiple vpcs
if *inArgs.OutputFormat == ARCHDRAWIOFormat || *inArgs.OutputFormat == DRAWIOFormat {
genOutFile = outFile
}
outFormat := getOutputFormat(inArgs)
output, err := og.Generate(outFormat, outFile)
output, err := og.Generate(outFormat, genOutFile)
if err != nil {
return fmt.Errorf("output generation error: %w", err)
return nil, fmt.Errorf("output generation error: %w", err)
}

// print to stdout as well
fmt.Println(output)

return nil
return output, nil
}

// The actual main function
Expand All @@ -84,12 +83,27 @@ func _main(cmdlineArgs []string) error {
if err != nil {
return fmt.Errorf("error generating cloud config from input vpc resources file: %w", err)
}
outFile := ""
if inArgs.OutputFile != nil {
outFile = *inArgs.OutputFile
}

outputPerVPC := make([]*vpcmodel.VPCAnalysisOutput, len(vpcConfigs))
i := 0
for _, vpcConfig := range vpcConfigs {
err = analysisPerVPCConfig(vpcConfig, inArgs)
if err != nil {
return err
vpcAnalysisOutput, err2 := analysisPerVPCConfig(vpcConfig, inArgs, outFile)
if err2 != nil {
return err2
}
outputPerVPC[i] = vpcAnalysisOutput
i++
}

out, err := vpcmodel.AggregateVPCsOutput(outputPerVPC, getOutputFormat(inArgs), outFile)
if err != nil {
return err
}
fmt.Println(out)

return nil
}
Expand Down
107 changes: 81 additions & 26 deletions pkg/ibmvpc/analysis_output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"testing"

Expand Down Expand Up @@ -63,7 +64,8 @@ func getTestFileName(testName string,
grouping bool,
format vpcmodel.OutFormat,
configName string,
numConfigs int) (
numConfigs int,
allVPCs bool) (
expectedFileName,
actualFileName string,
err error) {
Expand All @@ -72,7 +74,11 @@ func getTestFileName(testName string,
// if there are more than one vpc in the config, split to a file per one vpc analysis
baseName := testName
if numConfigs > 1 {
baseName += "_" + configName
if allVPCs {
baseName += "_all_vpcs"
} else {
baseName += "_" + configName
}
}

switch uc {
Expand Down Expand Up @@ -310,6 +316,11 @@ var tests = []*vpcGeneralTest{
useCases: []vpcmodel.OutputUseCase{vpcmodel.AllEndpoints},
format: vpcmodel.Text,
},
{
name: "experiments_env",
useCases: []vpcmodel.OutputUseCase{vpcmodel.AllEndpoints},
format: vpcmodel.JSON,
},
{
name: "multiple_vpcs",
useCases: []vpcmodel.OutputUseCase{vpcmodel.AllSubnets},
Expand Down Expand Up @@ -406,48 +417,92 @@ func getVPCConfigs(t *testing.T, tt *vpcGeneralTest) map[string]*vpcmodel.VPCCon
return vpcConfigs
}

func compareOrRegenerateOutputPerTest(t *testing.T,
mode testMode,
actualOutput string,
tt *vpcGeneralTest,
uc vpcmodel.OutputUseCase) error {
if mode == outputComparison {
expectedOutput, err := os.ReadFile(tt.expectedOutput[uc])
if err != nil {
t.Fatalf("err: %s", err)
}
expectedOutputStr := string(expectedOutput)
if cleanStr(expectedOutputStr) != cleanStr(actualOutput) {
compareTextualResult(expectedOutputStr, actualOutput)
t.Fatalf("output mismatch expected-vs-actual on test name: %s, use case: %d", tt.name, uc)
}
}

if mode == outputGeneration {
// create or override expected output file
if _, err := vpcmodel.WriteToFile(actualOutput, tt.expectedOutput[uc]); err != nil {
return err
}
}
return nil
}

func initTestFileNames(tt *vpcGeneralTest,
uc vpcmodel.OutputUseCase,
numConfigs int,
vpcName string,
allVPCs bool) error {
expectedFileName, actualFileName, err := getTestFileName(
tt.name, uc, tt.grouping, tt.format, vpcName, numConfigs, allVPCs)
if err != nil {
return err
}
tt.actualOutput[uc] = filepath.Join(getTestsDir(), actualFileName)
tt.expectedOutput[uc] = filepath.Join(getTestsDir(), expectedFileName)
return nil
}

// runTestPerUseCase runs the connectivity analysis for the required use case and compares/generates the output
func runTestPerUseCase(t *testing.T,
tt *vpcGeneralTest,
c map[string]*vpcmodel.VPCConfig,
uc vpcmodel.OutputUseCase,
mode testMode) error {
numConfigs := len(c)
allVPCsOutput := make([]*vpcmodel.VPCAnalysisOutput, numConfigs)
i := 0
for _, vpcConfig := range c {
expectedFileName, actualFileName, err := getTestFileName(tt.name, uc, tt.grouping, tt.format, vpcConfig.VPCName, numConfigs)
if err != nil {
if err := initTestFileNames(tt, uc, numConfigs, vpcConfig.VPC.Name(), false); err != nil {
return err
}
tt.actualOutput[uc] = filepath.Join(getTestsDir(), actualFileName)
tt.expectedOutput[uc] = filepath.Join(getTestsDir(), expectedFileName)
var actualOutput string

og, err := vpcmodel.NewOutputGenerator(vpcConfig, tt.grouping, uc, tt.format == vpcmodel.ARCHDRAWIO)
if err != nil {
return err
}
actualOutput, err = og.Generate(tt.format, tt.actualOutput[uc])
vpcOutput, err := og.Generate(tt.format, tt.actualOutput[uc])
if err != nil {
return err
}

if mode == outputComparison {
expectedOutput, err := os.ReadFile(tt.expectedOutput[uc])
if err != nil {
t.Fatalf("err: %s", err)
}
expectedOutputStr := string(expectedOutput)
if cleanStr(expectedOutputStr) != cleanStr(actualOutput) {
compareTextualResult(expectedOutputStr, actualOutput)
t.Fatalf("output mismatch expected-vs-actual on test name: %s, use case: %d", tt.name, uc)
}
allVPCsOutput[i] = vpcOutput
i++
if err := compareOrRegenerateOutputPerTest(t, mode, vpcOutput.Output, tt, uc); err != nil {
return err
}
}
// if more then one vpc -- compare also the aggregated output
if numConfigs > 1 {
if err := initTestFileNames(tt, uc, numConfigs, "", true); err != nil {
return err
}

// sort allVPCsOutput by vpc name
sort.Slice(allVPCsOutput, func(i, j int) bool {
return allVPCsOutput[i].VPCName < allVPCsOutput[j].VPCName
})

if mode == outputGeneration {
// create or override expected output file
if err := vpcmodel.WriteToFile(actualOutput, tt.expectedOutput[uc]); err != nil {
return err
}
actualOutput, err := vpcmodel.AggregateVPCsOutput(allVPCsOutput, tt.format, tt.actualOutput[uc])
if err != nil {
return err
}
if err := compareOrRegenerateOutputPerTest(t, mode, actualOutput, tt, uc); err != nil {
return err
}
}

Expand All @@ -462,8 +517,8 @@ func cleanStr(str string) string {
// compareTextualResult is called in case of output mismatch, to provide more details on the difference
func compareTextualResult(expected, actual string) {
var err1, err2 error
err1 = vpcmodel.WriteToFile(expected, filepath.Join(getTestsDir(), "expected.txt"))
err2 = vpcmodel.WriteToFile(actual, filepath.Join(getTestsDir(), "actual.txt"))
_, err1 = vpcmodel.WriteToFile(expected, filepath.Join(getTestsDir(), "expected.txt"))
_, err2 = vpcmodel.WriteToFile(actual, filepath.Join(getTestsDir(), "actual.txt"))
if err1 != nil || err2 != nil {
fmt.Printf("compareTextualResult: error writing actual/expected output to files: %s, %s \n", err1, err2)
}
Expand Down
Loading

0 comments on commit fccb150

Please sign in to comment.