github.com/grafana/tanka@v0.26.1-0.20240506093700-c22cfc35c21a/pkg/jsonnet/imports_test.go (about)

     1  package jsonnet
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"sync"
     9  	"testing"
    10  
    11  	"github.com/grafana/tanka/pkg/jsonnet/implementations/goimpl"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  // TestTransitiveImports checks that TransitiveImports is able to report all
    17  // recursive imports of a file
    18  func TestTransitiveImports(t *testing.T) {
    19  	imports, err := TransitiveImports("testdata/importTree")
    20  	fmt.Println(imports)
    21  	require.NoError(t, err)
    22  	assert.Equal(t, []string{
    23  		"main.jsonnet",
    24  		"trees.jsonnet",
    25  		"trees/apple.jsonnet",
    26  		"trees/cherry.jsonnet",
    27  		"trees/generic.libsonnet",
    28  		"trees/peach.jsonnet",
    29  	}, imports)
    30  }
    31  
    32  func BenchmarkGetSnippetHash(b *testing.B) {
    33  	for _, tc := range []struct {
    34  		name           string
    35  		importFromMain bool
    36  		expectedHash   string
    37  	}{
    38  		{
    39  			name:           "all-imported-from-main",
    40  			importFromMain: true,
    41  			expectedHash:   "ktY8NYZOoPacsNYrH7-DslRgLG54EMRdk3MQSM3vcUg=",
    42  		},
    43  		{
    44  			name:           "deeply-nested",
    45  			importFromMain: false,
    46  			expectedHash:   "W1Q_uS6jTGcsd7nvJfc-i785sqjBmOzfOAzqzhXVc0A=",
    47  		},
    48  	} {
    49  		b.Run(tc.name, func(b *testing.B) {
    50  			// Create a very large and complex project
    51  			tempDir := b.TempDir()
    52  			generateTestProject(b, tempDir, 1000, tc.importFromMain)
    53  
    54  			// Create a VM. It's important to reuse the same VM
    55  			// While there is a caching mechanism that normally shouldn't be shared in a benchmark iteration,
    56  			// it's useful to evaluate its impact here, because the caching will also improve the evaluation performance afterwards.
    57  			vm := goimpl.MakeRawVM([]string{tempDir}, nil, nil, 0)
    58  			content, err := os.ReadFile(filepath.Join(tempDir, "main.jsonnet"))
    59  			require.NoError(b, err)
    60  
    61  			// Run the benchmark
    62  			mainPath := filepath.Join(tempDir, "main.jsonnet")
    63  			c := string(content)
    64  			b.ResetTimer()
    65  			for i := 0; i < b.N; i++ {
    66  				fileHashes = sync.Map{}
    67  				hash, err := getSnippetHash(vm, mainPath, c)
    68  				require.NoError(b, err)
    69  				require.Equal(b, tc.expectedHash, hash)
    70  			}
    71  		})
    72  	}
    73  }
    74  
    75  func generateTestProject(t testing.TB, dir string, depth int, importAllFromMain bool) []string {
    76  	t.Helper()
    77  
    78  	const testFile = `
    79  	local localImport = <IMPORT>;
    80  	local myFunc = function() <IMPORT>;
    81  	
    82  	{
    83  		local this = self,
    84  	
    85  		attribute: {
    86  			name: 'test',
    87  			value: self.name,
    88  			otherValue: 'other ' + self.value,
    89  		},
    90  		nested: {
    91  			nested: {
    92  				nested: {
    93  					nested: {
    94  						nested1: {
    95  							nested: {
    96  								nested1: {
    97  									nested: {
    98  										attribute: <IMPORT>,
    99  									},
   100  								},
   101  								nested2: {
   102  									strValue: this.nested.nested.nested,
   103  								},
   104  							},
   105  						},
   106  						nested2: {
   107  							intValue: 1,
   108  							importValue: <IMPORT>,
   109  						},
   110  					},
   111  				},
   112  			},
   113  		},
   114  	
   115  		other: myFunc(),
   116  		useLocal: localImport,
   117  	}`
   118  
   119  	var allFiles []string
   120  
   121  	var mainContentSplit []string
   122  	for i := 0; i < depth; i++ {
   123  		mainContentSplit = append(mainContentSplit, fmt.Sprintf("(import 'file%d.libsonnet')", i))
   124  		filePath := filepath.Join(dir, fmt.Sprintf("file%d.libsonnet", i))
   125  		err := os.WriteFile(
   126  			filePath,
   127  			[]byte(strings.ReplaceAll(testFile, "<IMPORT>", fmt.Sprintf("import 'file%d.libsonnet'", i+1))),
   128  			0644,
   129  		)
   130  		require.NoError(t, err)
   131  		allFiles = append(allFiles, filePath)
   132  	}
   133  	if !importAllFromMain {
   134  		mainContentSplit = append(mainContentSplit, "import 'file0.libsonnet'")
   135  	}
   136  	require.NoError(t, os.WriteFile(filepath.Join(dir, "main.jsonnet"), []byte(strings.Join(mainContentSplit, " + ")), 0644))
   137  	allFiles = append(allFiles, filepath.Join(dir, "main.jsonnet"))
   138  	require.NoError(t, os.WriteFile(filepath.Join(dir, fmt.Sprintf("file%d.libsonnet", depth)), []byte(`"a string"`), 0644))
   139  	allFiles = append(allFiles, filepath.Join(dir, fmt.Sprintf("file%d.libsonnet", depth)))
   140  
   141  	return allFiles
   142  }