github.com/KusionStack/kpm@v0.8.4-0.20240326033734-dc72298a30e5/pkg/client/client_test.go (about)

     1  package client
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"log"
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/dominikbraun/graph"
    17  	"github.com/otiai10/copy"
    18  	"github.com/stretchr/testify/assert"
    19  	"kcl-lang.io/kpm/pkg/env"
    20  	"kcl-lang.io/kpm/pkg/git"
    21  	"kcl-lang.io/kpm/pkg/opt"
    22  	pkg "kcl-lang.io/kpm/pkg/package"
    23  	"kcl-lang.io/kpm/pkg/reporter"
    24  	"kcl-lang.io/kpm/pkg/runner"
    25  	"kcl-lang.io/kpm/pkg/utils"
    26  )
    27  
    28  const testDataDir = "test_data"
    29  
    30  func getTestDir(subDir string) string {
    31  	pwd, _ := os.Getwd()
    32  	testDir := filepath.Join(pwd, testDataDir)
    33  	testDir = filepath.Join(testDir, subDir)
    34  
    35  	return testDir
    36  }
    37  
    38  func initTestDir(subDir string) string {
    39  	testDir := getTestDir(subDir)
    40  	// clean the test data
    41  	_ = os.RemoveAll(testDir)
    42  	_ = os.Mkdir(testDir, 0755)
    43  
    44  	return testDir
    45  }
    46  
    47  // TestDownloadGit test download from oci registry.
    48  func TestDownloadOci(t *testing.T) {
    49  	testPath := filepath.Join(getTestDir("download"), "k8s_1.27")
    50  	err := os.MkdirAll(testPath, 0755)
    51  	assert.Equal(t, err, nil)
    52  
    53  	defer func() {
    54  		err := os.RemoveAll(getTestDir("download"))
    55  		if err != nil {
    56  			t.Errorf("Failed to remove directory: %v", err)
    57  		}
    58  	}()
    59  
    60  	depFromOci := pkg.Dependency{
    61  		Name:    "k8s",
    62  		Version: "1.27",
    63  		Source: pkg.Source{
    64  			Oci: &pkg.Oci{
    65  				Reg:  "ghcr.io",
    66  				Repo: "kcl-lang/k8s",
    67  				Tag:  "1.27",
    68  			},
    69  		},
    70  	}
    71  	kpmcli, err := NewKpmClient()
    72  	assert.Equal(t, err, nil)
    73  	dep, err := kpmcli.Download(&depFromOci, testPath)
    74  	assert.Equal(t, err, nil)
    75  	assert.Equal(t, dep.Name, "k8s")
    76  	assert.Equal(t, dep.FullName, "k8s_1.27")
    77  	assert.Equal(t, dep.Version, "1.27")
    78  	assert.Equal(t, dep.Sum, "xnYM1FWHAy3m+KcQMQb2rjZouTxumqYt6FGZpu2T4yM=")
    79  	assert.NotEqual(t, dep.Source.Oci, nil)
    80  	assert.Equal(t, dep.Source.Oci.Reg, "ghcr.io")
    81  	assert.Equal(t, dep.Source.Oci.Repo, "kcl-lang/k8s")
    82  	assert.Equal(t, dep.Source.Oci.Tag, "1.27")
    83  	assert.Equal(t, dep.LocalFullPath, testPath)
    84  
    85  	// Check whether the tar downloaded by `kpm add` has been deleted.
    86  	downloadPath := getTestDir("download")
    87  	assert.Equal(t, utils.DirExists(filepath.Join(downloadPath, "k8s_1.27.tar")), false)
    88  
    89  	assert.Equal(t, utils.DirExists(filepath.Join(downloadPath, "k8s_1.27")), true)
    90  	assert.Equal(t, utils.DirExists(filepath.Join(downloadPath, "k8s")), true)
    91  
    92  	// Check whether the reference and the dependency have the same hash.
    93  	hashDep, err := utils.HashDir(filepath.Join(downloadPath, "k8s_1.27"))
    94  	assert.Equal(t, err, nil)
    95  
    96  	depRefPath := filepath.Join(downloadPath, "k8s")
    97  	info, err := os.Lstat(depRefPath)
    98  	assert.Equal(t, err, nil)
    99  
   100  	if info.Mode()&os.ModeSymlink != 0 {
   101  		depRefPath, err = os.Readlink(depRefPath)
   102  		assert.Equal(t, err, nil)
   103  	}
   104  
   105  	hashRef, err := utils.HashDir(depRefPath)
   106  	assert.Equal(t, err, nil)
   107  	assert.Equal(t, hashDep, hashRef)
   108  }
   109  
   110  // TestDownloadLatestOci tests the case that the version is empty.
   111  func TestDownloadLatestOci(t *testing.T) {
   112  	testPath := filepath.Join(getTestDir("download"), "a_random_name")
   113  	defer func() {
   114  		err := os.RemoveAll(getTestDir("download"))
   115  		if err != nil {
   116  			t.Errorf("Failed to remove directory: %v", err)
   117  		}
   118  	}()
   119  	err := os.MkdirAll(testPath, 0755)
   120  	assert.Equal(t, err, nil)
   121  	depFromOci := pkg.Dependency{
   122  		Name:    "helloworld",
   123  		Version: "",
   124  		Source: pkg.Source{
   125  			Oci: &pkg.Oci{
   126  				Reg:  "ghcr.io",
   127  				Repo: "kcl-lang/helloworld",
   128  				Tag:  "",
   129  			},
   130  		},
   131  	}
   132  	kpmcli, err := NewKpmClient()
   133  	assert.Equal(t, err, nil)
   134  	dep, err := kpmcli.Download(&depFromOci, testPath)
   135  	assert.Equal(t, err, nil)
   136  	assert.Equal(t, dep.Name, "helloworld")
   137  	assert.Equal(t, dep.FullName, "helloworld_0.1.1")
   138  	assert.Equal(t, dep.Version, "0.1.1")
   139  	assert.Equal(t, dep.Sum, "7OO4YK2QuRWPq9C7KTzcWcti5yUnueCjptT3OXiPVeQ=")
   140  	assert.NotEqual(t, dep.Source.Oci, nil)
   141  	assert.Equal(t, dep.Source.Oci.Reg, "ghcr.io")
   142  	assert.Equal(t, dep.Source.Oci.Repo, "kcl-lang/helloworld")
   143  	assert.Equal(t, dep.Source.Oci.Tag, "0.1.1")
   144  	assert.Equal(t, dep.LocalFullPath, testPath+"0.1.1")
   145  	assert.Equal(t, err, nil)
   146  
   147  	// Check whether the tar downloaded by `kpm add` has been deleted.
   148  	assert.Equal(t, utils.DirExists(filepath.Join(testPath, "helloworld_0.1.1.tar")), false)
   149  
   150  	assert.Equal(t, utils.DirExists(filepath.Join(getTestDir("download"), "helloworld")), true)
   151  
   152  	// Check whether the reference and the dependency have the same hash.
   153  	hashDep, err := utils.HashDir(dep.LocalFullPath)
   154  	assert.Equal(t, err, nil)
   155  
   156  	depRefPath := filepath.Join(getTestDir("download"), "helloworld")
   157  	info, err := os.Lstat(depRefPath)
   158  	assert.Equal(t, err, nil)
   159  
   160  	if info.Mode()&os.ModeSymlink != 0 {
   161  		depRefPath, err = os.Readlink(depRefPath)
   162  		assert.Equal(t, err, nil)
   163  	}
   164  
   165  	hashRef, err := utils.HashDir(depRefPath)
   166  	assert.Equal(t, err, nil)
   167  	assert.Equal(t, hashDep, hashRef)
   168  }
   169  
   170  func TestDependencyGraph(t *testing.T) {
   171  	testDir := getTestDir("test_dependency_graph")
   172  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "kcl.mod.lock")), false)
   173  	kpmcli, err := NewKpmClient()
   174  	assert.Equal(t, err, nil)
   175  	kclPkg, err := kpmcli.LoadPkgFromPath(testDir)
   176  	assert.Equal(t, err, nil)
   177  
   178  	_, depGraph, err := kpmcli.InitGraphAndDownloadDeps(kclPkg)
   179  	assert.Equal(t, err, nil)
   180  	adjMap, err := depGraph.AdjacencyMap()
   181  	assert.Equal(t, err, nil)
   182  
   183  	edgeProp := graph.EdgeProperties{
   184  		Attributes: map[string]string{},
   185  		Weight:     0,
   186  		Data:       nil,
   187  	}
   188  
   189  	assert.Equal(t, adjMap,
   190  		map[string]map[string]graph.Edge[string]{
   191  			"dependency_graph@0.0.1": {
   192  				"teleport@0.1.0": {Source: "dependency_graph@0.0.1", Target: "teleport@0.1.0", Properties: edgeProp},
   193  				"rabbitmq@0.0.1": {Source: "dependency_graph@0.0.1", Target: "rabbitmq@0.0.1", Properties: edgeProp},
   194  				"agent@0.1.0":    {Source: "dependency_graph@0.0.1", Target: "agent@0.1.0", Properties: edgeProp},
   195  			},
   196  			"teleport@0.1.0": {
   197  				"k8s@1.28": {Source: "teleport@0.1.0", Target: "k8s@1.28", Properties: edgeProp},
   198  			},
   199  			"rabbitmq@0.0.1": {
   200  				"k8s@1.28": {Source: "rabbitmq@0.0.1", Target: "k8s@1.28", Properties: edgeProp},
   201  			},
   202  			"agent@0.1.0": {
   203  				"k8s@1.28": {Source: "agent@0.1.0", Target: "k8s@1.28", Properties: edgeProp},
   204  			},
   205  			"k8s@1.28": {},
   206  		},
   207  	)
   208  }
   209  
   210  func TestCyclicDependency(t *testing.T) {
   211  	testDir := getTestDir("test_cyclic_dependency")
   212  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "aaa")), true)
   213  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "aaa/kcl.mod")), true)
   214  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "bbb")), true)
   215  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "bbb/kcl.mod")), true)
   216  
   217  	pkg_path := filepath.Join(testDir, "aaa")
   218  
   219  	kpmcli, err := NewKpmClient()
   220  	assert.Equal(t, err, nil)
   221  	kclPkg, err := kpmcli.LoadPkgFromPath(pkg_path)
   222  	assert.Equal(t, err, nil)
   223  
   224  	currentDir, err := os.Getwd()
   225  	assert.Equal(t, err, nil)
   226  	err = os.Chdir(pkg_path)
   227  	assert.Equal(t, err, nil)
   228  
   229  	_, _, err = kpmcli.InitGraphAndDownloadDeps(kclPkg)
   230  	assert.Equal(t, err, reporter.NewErrorEvent(
   231  		reporter.CircularDependencyExist, nil, "adding bbb as a dependency results in a cycle",
   232  	))
   233  
   234  	err = os.Chdir(currentDir)
   235  	assert.Equal(t, err, nil)
   236  }
   237  
   238  func TestParseKclModFile(t *testing.T) {
   239  	// Create a temporary directory for testing
   240  	testDir := initTestDir("test_parse_kcl_mod_file")
   241  
   242  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "kcl.mod")), false)
   243  
   244  	kpmcli, err := NewKpmClient()
   245  	assert.Nil(t, err, "error creating KpmClient")
   246  
   247  	// Construct the modFilePath using filepath.Join
   248  	modFilePath := filepath.Join(testDir, "kcl.mod")
   249  
   250  	// Write modFileContent to modFilePath
   251  	modFileContent := `
   252          [dependencies]
   253          teleport = "0.1.0"
   254          rabbitmq = "0.0.1"
   255          gitdep = { git = "git://example.com/repo.git", tag = "v1.0.0" }
   256          localdep = { path = "/path/to/local/dependency" }
   257      `
   258  
   259  	err = os.WriteFile(modFilePath, []byte(modFileContent), 0644)
   260  	assert.Nil(t, err, "error writing mod file")
   261  
   262  	// Create a mock KclPkg
   263  	mockKclPkg, err := kpmcli.LoadPkgFromPath(testDir)
   264  
   265  	assert.Nil(t, err, "error loading package from path")
   266  
   267  	// Test the ParseKclModFile function
   268  	dependencies, err := kpmcli.ParseKclModFile(mockKclPkg)
   269  	assert.Nil(t, err, "error parsing kcl.mod file")
   270  
   271  	expectedDependencies := map[string]map[string]string{
   272  		"teleport": {"version": "0.1.0"},
   273  		"rabbitmq": {"version": "0.0.1"},
   274  		"gitdep":   {"git": "git://example.com/repo.git", "tag": "v1.0.0"},
   275  		"localdep": {"path": "/path/to/local/dependency"},
   276  	}
   277  
   278  	assert.Equal(t, expectedDependencies, dependencies, "parsed dependencies do not match expected dependencies")
   279  }
   280  
   281  func TestInitEmptyPkg(t *testing.T) {
   282  	testDir := initTestDir("test_init_empty_mod")
   283  	kclPkg := pkg.NewKclPkg(&opt.InitOptions{Name: "test_name", InitPath: testDir})
   284  	kpmcli, err := NewKpmClient()
   285  	assert.Equal(t, err, nil)
   286  	err = kpmcli.InitEmptyPkg(&kclPkg)
   287  	assert.Equal(t, err, nil)
   288  
   289  	testKclPkg, err := pkg.LoadKclPkg(testDir)
   290  	assert.Equal(t, err, nil)
   291  	assert.Equal(t, testKclPkg.ModFile.Pkg.Name, "test_name")
   292  	assert.Equal(t, testKclPkg.ModFile.Pkg.Version, "0.0.1")
   293  	assert.Equal(t, testKclPkg.ModFile.Pkg.Edition, runner.GetKclVersion())
   294  }
   295  
   296  func TestUpdateKclModAndLock(t *testing.T) {
   297  	testDir := initTestDir("test_data_add_deps")
   298  	// Init an empty package
   299  	kclPkg := pkg.NewKclPkg(&opt.InitOptions{
   300  		Name:     "test_add_deps",
   301  		InitPath: testDir,
   302  	})
   303  
   304  	kpmcli, err := NewKpmClient()
   305  	assert.Equal(t, err, nil)
   306  	err = kpmcli.InitEmptyPkg(&kclPkg)
   307  	assert.Equal(t, err, nil)
   308  
   309  	dep := pkg.Dependency{
   310  		Name:     "name",
   311  		FullName: "test_version",
   312  		Version:  "test_version",
   313  		Sum:      "test_sum",
   314  		Source: pkg.Source{
   315  			Git: &pkg.Git{
   316  				Url: "test_url",
   317  				Tag: "test_tag",
   318  			},
   319  		},
   320  	}
   321  
   322  	oci_dep := pkg.Dependency{
   323  		Name:     "oci_name",
   324  		FullName: "test_version",
   325  		Version:  "test_version",
   326  		Sum:      "test_sum",
   327  		Source: pkg.Source{
   328  			Oci: &pkg.Oci{
   329  				Reg:  "test_reg",
   330  				Repo: "test_repo",
   331  				Tag:  "test_tag",
   332  			},
   333  		},
   334  	}
   335  
   336  	kclPkg.Dependencies.Deps["oci_test"] = oci_dep
   337  	kclPkg.ModFile.Dependencies.Deps["oci_test"] = oci_dep
   338  
   339  	kclPkg.Dependencies.Deps["test"] = dep
   340  	kclPkg.ModFile.Dependencies.Deps["test"] = dep
   341  
   342  	err = kclPkg.ModFile.StoreModFile()
   343  	assert.Equal(t, err, nil)
   344  	err = kclPkg.LockDepsVersion()
   345  	assert.Equal(t, err, nil)
   346  
   347  	expectDir := getTestDir("expected")
   348  
   349  	if gotKclMod, err := os.ReadFile(filepath.Join(testDir, "kcl.mod")); os.IsNotExist(err) {
   350  		t.Errorf("failed to find kcl.mod.")
   351  	} else {
   352  		assert.Equal(t, len(kclPkg.Dependencies.Deps), 2)
   353  		assert.Equal(t, len(kclPkg.ModFile.Deps), 2)
   354  		expectKclMod, _ := os.ReadFile(filepath.Join(expectDir, "kcl.mod"))
   355  		expectKclModReverse, _ := os.ReadFile(filepath.Join(expectDir, "kcl.reverse.mod"))
   356  
   357  		gotKclModStr := utils.RmNewline(string(gotKclMod))
   358  		fmt.Printf("gotKclModStr: '%v'\n", gotKclModStr)
   359  		expectKclModStr := utils.RmNewline(string(expectKclMod))
   360  		fmt.Printf("expectKclModStr: '%v'\n", expectKclModStr)
   361  		expectKclModReverseStr := utils.RmNewline(string(expectKclModReverse))
   362  		fmt.Printf("expectKclModReverseStr: '%v'\n", expectKclModReverseStr)
   363  
   364  		assert.Equal(t,
   365  			(gotKclModStr == expectKclModStr || gotKclModStr == expectKclModReverseStr),
   366  			true,
   367  		)
   368  	}
   369  
   370  	if gotKclModLock, err := os.ReadFile(filepath.Join(testDir, "kcl.mod.lock")); os.IsNotExist(err) {
   371  		t.Errorf("failed to find kcl.mod.lock.")
   372  	} else {
   373  		assert.Equal(t, len(kclPkg.Dependencies.Deps), 2)
   374  		assert.Equal(t, len(kclPkg.ModFile.Deps), 2)
   375  		expectKclModLock, _ := os.ReadFile(filepath.Join(expectDir, "kcl.mod.lock"))
   376  		expectKclModLockReverse, _ := os.ReadFile(filepath.Join(expectDir, "kcl.mod.reverse.lock"))
   377  
   378  		gotKclModLockStr := utils.RmNewline(string(gotKclModLock))
   379  		fmt.Printf("gotKclModLockStr: '%v'\n", gotKclModLockStr)
   380  		expectKclModLockStr := utils.RmNewline(string(expectKclModLock))
   381  		fmt.Printf("expectKclModLockStr: '%v'\n", expectKclModLockStr)
   382  		expectKclModLockReverseStr := utils.RmNewline(string(expectKclModLockReverse))
   383  		fmt.Printf("expectKclModLockReverseStr: '%v'\n", expectKclModLockReverseStr)
   384  
   385  		assert.Equal(t,
   386  			(gotKclModLockStr == expectKclModLockStr) || (gotKclModLockStr == expectKclModLockReverseStr),
   387  			true,
   388  		)
   389  	}
   390  }
   391  
   392  func TestVendorDeps(t *testing.T) {
   393  	testDir := getTestDir("resolve_deps")
   394  	kpm_home := filepath.Join(testDir, "kpm_home")
   395  	os.RemoveAll(filepath.Join(testDir, "my_kcl"))
   396  	kcl1Sum, _ := utils.HashDir(filepath.Join(kpm_home, "kcl1"))
   397  	kcl2Sum, _ := utils.HashDir(filepath.Join(kpm_home, "kcl2"))
   398  
   399  	depKcl1 := pkg.Dependency{
   400  		Name:     "kcl1",
   401  		FullName: "kcl1",
   402  		Sum:      kcl1Sum,
   403  	}
   404  
   405  	depKcl2 := pkg.Dependency{
   406  		Name:     "kcl2",
   407  		FullName: "kcl2",
   408  		Sum:      kcl2Sum,
   409  	}
   410  
   411  	kclPkg := pkg.KclPkg{
   412  		ModFile: pkg.ModFile{
   413  			HomePath: filepath.Join(testDir, "my_kcl"),
   414  			// Whether the current package uses the vendor mode
   415  			// In the vendor mode, kpm will look for the package in the vendor subdirectory
   416  			// in the current package directory.
   417  			VendorMode: false,
   418  			Dependencies: pkg.Dependencies{
   419  				Deps: map[string]pkg.Dependency{
   420  					"kcl1": depKcl1,
   421  					"kcl2": depKcl2,
   422  				},
   423  			},
   424  		},
   425  		HomePath: filepath.Join(testDir, "my_kcl"),
   426  		// The dependencies in the current kcl package are the dependencies of kcl.mod.lock,
   427  		// not the dependencies in kcl.mod.
   428  		Dependencies: pkg.Dependencies{
   429  			Deps: map[string]pkg.Dependency{
   430  				"kcl1": depKcl1,
   431  				"kcl2": depKcl2,
   432  			},
   433  		},
   434  	}
   435  
   436  	mykclVendorPath := filepath.Join(filepath.Join(testDir, "my_kcl"), "vendor")
   437  	assert.Equal(t, utils.DirExists(mykclVendorPath), false)
   438  	kpmcli, err := NewKpmClient()
   439  	kpmcli.homePath = kpm_home
   440  	assert.Equal(t, err, nil)
   441  	err = kpmcli.VendorDeps(&kclPkg)
   442  	assert.Equal(t, err, nil)
   443  	assert.Equal(t, utils.DirExists(mykclVendorPath), true)
   444  	assert.Equal(t, utils.DirExists(filepath.Join(mykclVendorPath, "kcl1")), true)
   445  	assert.Equal(t, utils.DirExists(filepath.Join(mykclVendorPath, "kcl2")), true)
   446  
   447  	maps, err := kpmcli.ResolveDepsIntoMap(&kclPkg)
   448  	assert.Equal(t, err, nil)
   449  	assert.Equal(t, len(maps), 2)
   450  
   451  	os.RemoveAll(filepath.Join(testDir, "my_kcl"))
   452  }
   453  
   454  func TestResolveDepsWithOnlyKclMod(t *testing.T) {
   455  	testDir := getTestDir("resolve_dep_with_kclmod")
   456  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "kcl.mod.lock")), false)
   457  	kpmcli, err := NewKpmClient()
   458  	assert.Equal(t, err, nil)
   459  	kclPkg, err := kpmcli.LoadPkgFromPath(testDir)
   460  	assert.Equal(t, err, nil)
   461  	depsMap, err := kpmcli.ResolveDepsIntoMap(kclPkg)
   462  	assert.Equal(t, err, nil)
   463  	assert.Equal(t, len(depsMap), 1)
   464  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, "kcl.mod.lock")), true)
   465  	assert.Equal(t, depsMap["k8s"], filepath.Join(kpmcli.homePath, "k8s_1.17"))
   466  	assert.Equal(t, utils.DirExists(filepath.Join(kpmcli.homePath, "k8s_1.17")), true)
   467  	defer func() {
   468  		err := os.Remove(filepath.Join(testDir, "kcl.mod.lock"))
   469  		assert.Equal(t, err, nil)
   470  	}()
   471  }
   472  
   473  func TestResolveDepsVendorMode(t *testing.T) {
   474  	testDir := getTestDir("resolve_deps")
   475  	kpm_home := filepath.Join(testDir, "kpm_home")
   476  	home_path := filepath.Join(testDir, "my_kcl_resolve_deps_vendor_mode")
   477  	os.RemoveAll(home_path)
   478  	kcl1Sum, _ := utils.HashDir(filepath.Join(kpm_home, "kcl1"))
   479  	kcl2Sum, _ := utils.HashDir(filepath.Join(kpm_home, "kcl2"))
   480  
   481  	depKcl1 := pkg.Dependency{
   482  		Name:     "kcl1",
   483  		FullName: "kcl1",
   484  		Sum:      kcl1Sum,
   485  	}
   486  
   487  	depKcl2 := pkg.Dependency{
   488  		Name:     "kcl2",
   489  		FullName: "kcl2",
   490  		Sum:      kcl2Sum,
   491  	}
   492  
   493  	kclPkg := pkg.KclPkg{
   494  		ModFile: pkg.ModFile{
   495  			HomePath: home_path,
   496  			// Whether the current package uses the vendor mode
   497  			// In the vendor mode, kpm will look for the package in the vendor subdirectory
   498  			// in the current package directory.
   499  			VendorMode: true,
   500  			Dependencies: pkg.Dependencies{
   501  				Deps: map[string]pkg.Dependency{
   502  					"kcl1": depKcl1,
   503  					"kcl2": depKcl2,
   504  				},
   505  			},
   506  		},
   507  		HomePath: home_path,
   508  		// The dependencies in the current kcl package are the dependencies of kcl.mod.lock,
   509  		// not the dependencies in kcl.mod.
   510  		Dependencies: pkg.Dependencies{
   511  			Deps: map[string]pkg.Dependency{
   512  				"kcl1": depKcl1,
   513  				"kcl2": depKcl2,
   514  			},
   515  		},
   516  	}
   517  	mySearchPath := filepath.Join(home_path, "vendor")
   518  	assert.Equal(t, utils.DirExists(mySearchPath), false)
   519  
   520  	kpmcli, err := NewKpmClient()
   521  	assert.Equal(t, err, nil)
   522  	kpmcli.homePath = kpm_home
   523  
   524  	maps, err := kpmcli.ResolveDepsIntoMap(&kclPkg)
   525  	assert.Equal(t, err, nil)
   526  	assert.Equal(t, len(maps), 2)
   527  	checkDepsMapInSearchPath(t, depKcl1, mySearchPath, maps)
   528  
   529  	kclPkg.SetVendorMode(false)
   530  	maps, err = kpmcli.ResolveDepsIntoMap(&kclPkg)
   531  	assert.Equal(t, err, nil)
   532  	assert.Equal(t, len(maps), 2)
   533  	checkDepsMapInSearchPath(t, depKcl1, kpm_home, maps)
   534  
   535  	os.RemoveAll(home_path)
   536  }
   537  
   538  func TestCompileWithEntryFile(t *testing.T) {
   539  	testDir := getTestDir("resolve_deps")
   540  	kpm_home := filepath.Join(testDir, "kpm_home")
   541  	home_path := filepath.Join(testDir, "my_kcl_compile")
   542  	vendor_path := filepath.Join(home_path, "vendor")
   543  	entry_file := filepath.Join(home_path, "main.k")
   544  	os.RemoveAll(vendor_path)
   545  
   546  	kcl1Sum, _ := utils.HashDir(filepath.Join(kpm_home, "kcl1"))
   547  	depKcl1 := pkg.Dependency{
   548  		Name:     "kcl1",
   549  		FullName: "kcl1",
   550  		Sum:      kcl1Sum,
   551  	}
   552  	kcl2Sum, _ := utils.HashDir(filepath.Join(kpm_home, "kcl2"))
   553  	depKcl2 := pkg.Dependency{
   554  		Name:     "kcl2",
   555  		FullName: "kcl2",
   556  		Sum:      kcl2Sum,
   557  	}
   558  
   559  	kclPkg := pkg.KclPkg{
   560  		ModFile: pkg.ModFile{
   561  			HomePath: home_path,
   562  			// Whether the current package uses the vendor mode
   563  			// In the vendor mode, kpm will look for the package in the vendor subdirectory
   564  			// in the current package directory.
   565  			VendorMode: true,
   566  			Dependencies: pkg.Dependencies{
   567  				Deps: map[string]pkg.Dependency{
   568  					"kcl1": depKcl1,
   569  					"kcl2": depKcl2,
   570  				},
   571  			},
   572  		},
   573  		HomePath: home_path,
   574  		// The dependencies in the current kcl package are the dependencies of kcl.mod.lock,
   575  		// not the dependencies in kcl.mod.
   576  		Dependencies: pkg.Dependencies{
   577  			Deps: map[string]pkg.Dependency{
   578  				"kcl1": depKcl1,
   579  				"kcl2": depKcl2,
   580  			},
   581  		},
   582  	}
   583  
   584  	assert.Equal(t, utils.DirExists(vendor_path), false)
   585  
   586  	compiler := runner.DefaultCompiler()
   587  	compiler.AddKFile(entry_file)
   588  	kpmcli, err := NewKpmClient()
   589  	assert.Equal(t, err, nil)
   590  	kpmcli.homePath = kpm_home
   591  	result, err := kpmcli.Compile(&kclPkg, compiler)
   592  	assert.Equal(t, err, nil)
   593  	assert.Equal(t, utils.DirExists(filepath.Join(vendor_path, "kcl1")), true)
   594  	assert.Equal(t, utils.DirExists(filepath.Join(vendor_path, "kcl2")), true)
   595  	assert.Equal(t, result.GetRawYamlResult(), "c1: 1\nc2: 2")
   596  	os.RemoveAll(vendor_path)
   597  
   598  	kclPkg.SetVendorMode(false)
   599  	assert.Equal(t, utils.DirExists(vendor_path), false)
   600  
   601  	result, err = kpmcli.Compile(&kclPkg, compiler)
   602  	assert.Equal(t, err, nil)
   603  	assert.Equal(t, utils.DirExists(vendor_path), false)
   604  	assert.Equal(t, result.GetRawYamlResult(), "c1: 1\nc2: 2")
   605  	os.RemoveAll(vendor_path)
   606  }
   607  
   608  func checkDepsMapInSearchPath(t *testing.T, dep pkg.Dependency, searchPath string, maps map[string]string) {
   609  	assert.Equal(t, maps[dep.Name], filepath.Join(searchPath, dep.FullName))
   610  	assert.Equal(t, utils.DirExists(filepath.Join(searchPath, dep.FullName)), true)
   611  }
   612  
   613  func TestPackageCurrentPkgPath(t *testing.T) {
   614  	testDir := getTestDir("tar_kcl_pkg")
   615  
   616  	kclPkg, err := pkg.LoadKclPkg(testDir)
   617  	assert.Equal(t, err, nil)
   618  	assert.Equal(t, kclPkg.GetPkgTag(), "0.0.1")
   619  	assert.Equal(t, kclPkg.GetPkgName(), "test_tar")
   620  	assert.Equal(t, kclPkg.GetPkgFullName(), "test_tar-0.0.1")
   621  	assert.Equal(t, kclPkg.GetPkgTarName(), "test_tar-0.0.1.tar")
   622  
   623  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, kclPkg.GetPkgTarName())), false)
   624  
   625  	kpmcli, err := NewKpmClient()
   626  	assert.Equal(t, err, nil)
   627  	path, err := kpmcli.PackagePkg(kclPkg, true)
   628  	assert.Equal(t, err, nil)
   629  	assert.Equal(t, path, filepath.Join(testDir, kclPkg.GetPkgTarName()))
   630  	assert.Equal(t, utils.DirExists(filepath.Join(testDir, kclPkg.GetPkgTarName())), true)
   631  	defer func() {
   632  		if r := os.RemoveAll(filepath.Join(testDir, kclPkg.GetPkgTarName())); r != nil {
   633  			err = fmt.Errorf("panic: %v", r)
   634  		}
   635  	}()
   636  }
   637  
   638  func TestResolveMetadataInJsonStr(t *testing.T) {
   639  	originalValue := os.Getenv(env.PKG_PATH)
   640  	defer os.Setenv(env.PKG_PATH, originalValue)
   641  
   642  	testDir := getTestDir("resolve_metadata")
   643  
   644  	testHomePath := filepath.Join(filepath.Dir(testDir), "test_home_path")
   645  	prepareKpmHomeInPath(testHomePath)
   646  	defer os.RemoveAll(testHomePath)
   647  
   648  	os.Setenv(env.PKG_PATH, testHomePath)
   649  
   650  	kclpkg, err := pkg.LoadKclPkg(testDir)
   651  	assert.Equal(t, err, nil)
   652  
   653  	globalPkgPath, _ := env.GetAbsPkgPath()
   654  	kpmcli, err := NewKpmClient()
   655  	assert.Equal(t, err, nil)
   656  	res, err := kpmcli.ResolveDepsMetadataInJsonStr(kclpkg, true)
   657  	assert.Equal(t, err, nil)
   658  
   659  	expectedDep := pkg.Dependencies{
   660  		Deps: make(map[string]pkg.Dependency),
   661  	}
   662  
   663  	expectedDep.Deps["konfig"] = pkg.Dependency{
   664  		Name:          "konfig",
   665  		FullName:      "konfig_v0.0.1",
   666  		LocalFullPath: filepath.Join(globalPkgPath, "konfig_v0.0.1"),
   667  	}
   668  
   669  	expectedDepStr, err := json.Marshal(expectedDep)
   670  	assert.Equal(t, err, nil)
   671  
   672  	assert.Equal(t, res, string(expectedDepStr))
   673  
   674  	vendorDir := filepath.Join(testDir, "vendor")
   675  	if utils.DirExists(vendorDir) {
   676  		err = os.RemoveAll(vendorDir)
   677  		assert.Equal(t, err, nil)
   678  	}
   679  	kclpkg.SetVendorMode(true)
   680  	res, err = kpmcli.ResolveDepsMetadataInJsonStr(kclpkg, true)
   681  	assert.Equal(t, err, nil)
   682  	assert.Equal(t, utils.DirExists(vendorDir), true)
   683  	assert.Equal(t, utils.DirExists(filepath.Join(vendorDir, "konfig_v0.0.1")), true)
   684  
   685  	expectedDep.Deps["konfig"] = pkg.Dependency{
   686  		Name:          "konfig",
   687  		FullName:      "konfig_v0.0.1",
   688  		LocalFullPath: filepath.Join(vendorDir, "konfig_v0.0.1"),
   689  	}
   690  
   691  	expectedDepStr, err = json.Marshal(expectedDep)
   692  	assert.Equal(t, err, nil)
   693  
   694  	assert.Equal(t, res, string(expectedDepStr))
   695  	if utils.DirExists(vendorDir) {
   696  		err = os.RemoveAll(vendorDir)
   697  		assert.Equal(t, err, nil)
   698  	}
   699  
   700  	kclpkg, err = kpmcli.LoadPkgFromPath(testDir)
   701  	assert.Equal(t, err, nil)
   702  	kpmcli.homePath = "not_exist"
   703  	res, err = kpmcli.ResolveDepsMetadataInJsonStr(kclpkg, false)
   704  	fmt.Printf("err: %v\n", err)
   705  	assert.Equal(t, err, nil)
   706  	assert.Equal(t, utils.DirExists(vendorDir), false)
   707  	assert.Equal(t, utils.DirExists(filepath.Join(vendorDir, "konfig_v0.0.1")), false)
   708  	jsonPath, err := json.Marshal(filepath.Join("not_exist", "konfig_v0.0.1"))
   709  	assert.Equal(t, err, nil)
   710  	expectedStr := fmt.Sprintf("{\"packages\":{\"konfig\":{\"name\":\"konfig\",\"manifest_path\":%s}}}", string(jsonPath))
   711  	assert.Equal(t, res, expectedStr)
   712  	defer func() {
   713  		if r := os.RemoveAll(filepath.Join("not_exist", "konfig_v0.0.1")); r != nil {
   714  			err = fmt.Errorf("panic: %v", r)
   715  		}
   716  	}()
   717  }
   718  
   719  func prepareKpmHomeInPath(path string) {
   720  	dirPath := filepath.Join(filepath.Join(path, ".kpm"), "config")
   721  	_ = os.MkdirAll(dirPath, 0755)
   722  
   723  	filePath := filepath.Join(dirPath, "kpm.json")
   724  
   725  	_ = os.WriteFile(filePath, []byte("{\"DefaultOciRegistry\":\"ghcr.io\",\"DefaultOciRepo\":\"awesome-kusion\"}"), 0644)
   726  }
   727  
   728  func TestPkgWithInVendorMode(t *testing.T) {
   729  	testDir := getTestDir("test_pkg_with_vendor")
   730  	kcl1Path := filepath.Join(testDir, "kcl1")
   731  
   732  	createKclPkg1 := func() {
   733  		assert.Equal(t, utils.DirExists(kcl1Path), false)
   734  		err := os.MkdirAll(kcl1Path, 0755)
   735  		assert.Equal(t, err, nil)
   736  	}
   737  
   738  	defer func() {
   739  		if err := os.RemoveAll(kcl1Path); err != nil {
   740  			log.Printf("failed to close file: %v", err)
   741  		}
   742  	}()
   743  
   744  	createKclPkg1()
   745  
   746  	initOpts := opt.InitOptions{
   747  		Name:     "kcl1",
   748  		InitPath: kcl1Path,
   749  	}
   750  	kclPkg1 := pkg.NewKclPkg(&initOpts)
   751  	kpmcli, err := NewKpmClient()
   752  	assert.Equal(t, err, nil)
   753  	_, err = kpmcli.AddDepWithOpts(&kclPkg1, &opt.AddOptions{
   754  		LocalPath: "localPath",
   755  		RegistryOpts: opt.RegistryOptions{
   756  			Local: &opt.LocalOptions{
   757  				Path: filepath.Join(testDir, "kcl2"),
   758  			},
   759  		},
   760  	})
   761  
   762  	assert.Equal(t, err, nil)
   763  
   764  	// package the kcl1 into tar in vendor mode.
   765  	tarPath, err := kpmcli.PackagePkg(&kclPkg1, true)
   766  	assert.Equal(t, err, nil)
   767  	hasSubDir, err := hasSubdirInTar(tarPath, "vendor")
   768  	assert.Equal(t, err, nil)
   769  	assert.Equal(t, hasSubDir, true)
   770  
   771  	// clean the kcl1
   772  	err = os.RemoveAll(kcl1Path)
   773  	assert.Equal(t, err, nil)
   774  
   775  	createKclPkg1()
   776  	// package the kcl1 into tar in non-vendor mode.
   777  	tarPath, err = kpmcli.PackagePkg(&kclPkg1, false)
   778  	assert.Equal(t, err, nil)
   779  	hasSubDir, err = hasSubdirInTar(tarPath, "vendor")
   780  	assert.Equal(t, err, nil)
   781  	assert.Equal(t, hasSubDir, false)
   782  }
   783  
   784  // check if the tar file contains the subdir
   785  func hasSubdirInTar(tarPath, subdir string) (bool, error) {
   786  	f, err := os.Open(tarPath)
   787  	if err != nil {
   788  		return false, err
   789  	}
   790  	defer f.Close()
   791  
   792  	tr := tar.NewReader(f)
   793  	for {
   794  		hdr, err := tr.Next()
   795  		if err == io.EOF {
   796  			break
   797  		}
   798  		if hdr.Typeflag == tar.TypeDir && filepath.Base(hdr.Name) == subdir {
   799  			return true, nil
   800  		}
   801  	}
   802  
   803  	return false, nil
   804  }
   805  
   806  func TestNewKpmClient(t *testing.T) {
   807  	kpmcli, err := NewKpmClient()
   808  	assert.Equal(t, err, nil)
   809  	kpmhome, err := env.GetAbsPkgPath()
   810  	assert.Equal(t, err, nil)
   811  	assert.Equal(t, kpmcli.homePath, kpmhome)
   812  	assert.Equal(t, kpmcli.GetSettings().KpmConfFile, filepath.Join(kpmhome, ".kpm", "config", "kpm.json"))
   813  	assert.Equal(t, kpmcli.GetSettings().CredentialsFile, filepath.Join(kpmhome, ".kpm", "config", "config.json"))
   814  	assert.Equal(t, kpmcli.GetSettings().Conf.DefaultOciRepo, "kcl-lang")
   815  	assert.Equal(t, kpmcli.GetSettings().Conf.DefaultOciRegistry, "ghcr.io")
   816  	assert.Equal(t, kpmcli.GetSettings().Conf.DefaultOciPlainHttp, false)
   817  }
   818  
   819  func TestParseOciOptionFromString(t *testing.T) {
   820  	kpmcli, err := NewKpmClient()
   821  	assert.Equal(t, err, nil)
   822  	oci_ref_with_tag := "test_oci_repo:test_oci_tag"
   823  	ociOption, err := kpmcli.ParseOciOptionFromString(oci_ref_with_tag, "test_tag")
   824  	assert.Equal(t, err, nil)
   825  	assert.Equal(t, ociOption.PkgName, "")
   826  	assert.Equal(t, ociOption.Reg, "ghcr.io")
   827  	assert.Equal(t, ociOption.Repo, "kcl-lang/test_oci_repo")
   828  	assert.Equal(t, ociOption.Tag, "test_oci_tag")
   829  
   830  	oci_ref_without_tag := "test_oci_repo:test_oci_tag"
   831  	ociOption, err = kpmcli.ParseOciOptionFromString(oci_ref_without_tag, "test_tag")
   832  	assert.Equal(t, err, nil)
   833  	assert.Equal(t, ociOption.PkgName, "")
   834  	assert.Equal(t, ociOption.Reg, "ghcr.io")
   835  	assert.Equal(t, ociOption.Repo, "kcl-lang/test_oci_repo")
   836  	assert.Equal(t, ociOption.Tag, "test_oci_tag")
   837  
   838  	oci_url_with_tag := "oci://test_reg/test_oci_repo"
   839  	ociOption, err = kpmcli.ParseOciOptionFromString(oci_url_with_tag, "test_tag")
   840  	assert.Equal(t, err, nil)
   841  	assert.Equal(t, ociOption.PkgName, "")
   842  	assert.Equal(t, ociOption.Reg, "test_reg")
   843  	assert.Equal(t, ociOption.Repo, "/test_oci_repo")
   844  	assert.Equal(t, ociOption.Tag, "test_tag")
   845  }
   846  
   847  func TestUpdateWithKclMod(t *testing.T) {
   848  	kpmcli, err := NewKpmClient()
   849  	assert.Equal(t, err, nil)
   850  
   851  	testDir := getTestDir("test_update")
   852  	src_testDir := filepath.Join(testDir, "test_update_kcl_mod")
   853  	dest_testDir := filepath.Join(testDir, "test_update_kcl_mod_tmp")
   854  	err = copy.Copy(src_testDir, dest_testDir)
   855  	assert.Equal(t, err, nil)
   856  
   857  	kclPkg, err := pkg.LoadKclPkg(dest_testDir)
   858  	assert.Equal(t, err, nil)
   859  	err = kpmcli.UpdateDeps(kclPkg)
   860  	assert.Equal(t, err, nil)
   861  	got_lock_file := filepath.Join(dest_testDir, "kcl.mod.lock")
   862  	got_content, err := os.ReadFile(got_lock_file)
   863  	assert.Equal(t, err, nil)
   864  
   865  	expected_path := filepath.Join(dest_testDir, "expected")
   866  	expected_content, err := os.ReadFile(expected_path)
   867  
   868  	assert.Equal(t, err, nil)
   869  	expect := strings.ReplaceAll(string(expected_content), "\r\n", "\n")
   870  	assert.Equal(t, string(got_content), expect)
   871  
   872  	defer func() {
   873  		err := os.RemoveAll(dest_testDir)
   874  		assert.Equal(t, err, nil)
   875  	}()
   876  }
   877  
   878  func TestUpdateWithKclModlock(t *testing.T) {
   879  	kpmcli, err := NewKpmClient()
   880  	assert.Equal(t, err, nil)
   881  
   882  	testDir := getTestDir("test_update")
   883  	src_testDir := filepath.Join(testDir, "test_update_kcl_mod_lock")
   884  	dest_testDir := filepath.Join(testDir, "test_update_kcl_mod_lock_tmp")
   885  	err = copy.Copy(src_testDir, dest_testDir)
   886  	assert.Equal(t, err, nil)
   887  
   888  	kclPkg, err := pkg.LoadKclPkg(dest_testDir)
   889  	assert.Equal(t, err, nil)
   890  	err = kpmcli.UpdateDeps(kclPkg)
   891  	assert.Equal(t, err, nil)
   892  	got_lock_file := filepath.Join(dest_testDir, "kcl.mod.lock")
   893  	got_content, err := os.ReadFile(got_lock_file)
   894  	assert.Equal(t, err, nil)
   895  
   896  	expected_path := filepath.Join(dest_testDir, "expected")
   897  	expected_content, err := os.ReadFile(expected_path)
   898  
   899  	assert.Equal(t, err, nil)
   900  	assert.Equal(t, string(got_content), string(expected_content))
   901  
   902  	defer func() {
   903  		err := os.RemoveAll(dest_testDir)
   904  		assert.Equal(t, err, nil)
   905  	}()
   906  }
   907  
   908  func TestMetadataOffline(t *testing.T) {
   909  	kpmcli, err := NewKpmClient()
   910  	assert.Equal(t, err, nil)
   911  
   912  	testDir := getTestDir("test_metadata_offline")
   913  	kclMod := filepath.Join(testDir, "kcl.mod")
   914  	uglyKclMod := filepath.Join(testDir, "ugly.kcl.mod")
   915  	BeautifulKclMod := filepath.Join(testDir, "beautiful.kcl.mod")
   916  
   917  	uglyContent, err := os.ReadFile(uglyKclMod)
   918  	assert.Equal(t, err, nil)
   919  	err = copy.Copy(uglyKclMod, kclMod)
   920  	assert.Equal(t, err, nil)
   921  	defer func() {
   922  		err := os.Remove(kclMod)
   923  		assert.Equal(t, err, nil)
   924  	}()
   925  
   926  	beautifulContent, err := os.ReadFile(BeautifulKclMod)
   927  	assert.Equal(t, err, nil)
   928  	kclPkg, err := pkg.LoadKclPkg(testDir)
   929  	assert.Equal(t, err, nil)
   930  
   931  	res, err := kpmcli.ResolveDepsMetadataInJsonStr(kclPkg, false)
   932  	assert.Equal(t, err, nil)
   933  	assert.Equal(t, res, "{\"packages\":{}}")
   934  	content_after_metadata, err := os.ReadFile(kclMod)
   935  	assert.Equal(t, err, nil)
   936  	assert.Equal(t, string(content_after_metadata), string(uglyContent))
   937  
   938  	res, err = kpmcli.ResolveDepsMetadataInJsonStr(kclPkg, true)
   939  	assert.Equal(t, err, nil)
   940  	assert.Equal(t, res, "{\"packages\":{}}")
   941  	content_after_metadata, err = os.ReadFile(kclMod)
   942  	assert.Equal(t, err, nil)
   943  	assert.Equal(t, utils.RmNewline(string(content_after_metadata)), utils.RmNewline(string(beautifulContent)))
   944  }
   945  
   946  func TestAddWithNoSumCheck(t *testing.T) {
   947  	pkgPath := getTestDir("test_add_no_sum_check")
   948  	err := copy.Copy(filepath.Join(pkgPath, "kcl.mod.bak"), filepath.Join(pkgPath, "kcl.mod"))
   949  	assert.Equal(t, err, nil)
   950  
   951  	kpmcli, err := NewKpmClient()
   952  	assert.Equal(t, err, nil)
   953  	kclPkg, err := kpmcli.LoadPkgFromPath(pkgPath)
   954  	assert.Equal(t, err, nil)
   955  
   956  	opts := opt.AddOptions{
   957  		LocalPath: pkgPath,
   958  		RegistryOpts: opt.RegistryOptions{
   959  			Oci: &opt.OciOptions{
   960  				Reg:     "ghcr.io",
   961  				Repo:    "kcl-lang",
   962  				PkgName: "helloworld",
   963  				Tag:     "0.1.0",
   964  			},
   965  		},
   966  		NoSumCheck: true,
   967  	}
   968  
   969  	_, err = kpmcli.AddDepWithOpts(kclPkg, &opts)
   970  	assert.Equal(t, err, nil)
   971  	assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), false)
   972  
   973  	opts.NoSumCheck = false
   974  	_, err = kpmcli.AddDepWithOpts(kclPkg, &opts)
   975  	assert.Equal(t, err, nil)
   976  	assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), true)
   977  	defer func() {
   978  		_ = os.Remove(filepath.Join(pkgPath, "kcl.mod.lock"))
   979  		_ = os.Remove(filepath.Join(pkgPath, "kcl.mod"))
   980  	}()
   981  }
   982  
   983  func TestRunWithNoSumCheck(t *testing.T) {
   984  	pkgPath := getTestDir("test_run_no_sum_check")
   985  
   986  	kpmcli, err := NewKpmClient()
   987  	assert.Equal(t, err, nil)
   988  
   989  	opts := opt.DefaultCompileOptions()
   990  	opts.SetNoSumCheck(true)
   991  	opts.SetPkgPath(pkgPath)
   992  
   993  	_, err = kpmcli.CompileWithOpts(opts)
   994  	assert.Equal(t, err, nil)
   995  	assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), false)
   996  
   997  	opts = opt.DefaultCompileOptions()
   998  	opts.SetPkgPath(pkgPath)
   999  	opts.SetNoSumCheck(false)
  1000  	_, err = kpmcli.CompileWithOpts(opts)
  1001  	assert.Equal(t, err, nil)
  1002  	assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), true)
  1003  
  1004  	defer func() {
  1005  		_ = os.Remove(filepath.Join(pkgPath, "kcl.mod.lock"))
  1006  	}()
  1007  }
  1008  
  1009  func TestRunGit(t *testing.T) {
  1010  	kpmcli, err := NewKpmClient()
  1011  	assert.Equal(t, err, nil)
  1012  
  1013  	testPath := getTestDir("test_run_git")
  1014  
  1015  	opts := opt.DefaultCompileOptions()
  1016  	gitOpts := git.NewCloneOptions("https://github.com/KusionStack/catalog", "", "0.1.2", "", filepath.Join(testPath, "catalog"), nil)
  1017  	defer func() {
  1018  		_ = os.RemoveAll(filepath.Join(testPath, "catalog"))
  1019  	}()
  1020  
  1021  	testCases := []struct {
  1022  		entryPath  string
  1023  		expectFile string
  1024  	}{
  1025  		{"models/samples/hellocollaset/prod/main.k", "expect1.json"},
  1026  		{"models/samples/pgadmin/base/base.k", "expect2.json"},
  1027  		{"models/samples/wordpress/prod/main.k", "expect3.json"},
  1028  	}
  1029  
  1030  	for _, tc := range testCases {
  1031  		opts.SetEntries([]string{tc.entryPath})
  1032  		result, err := kpmcli.CompileGitPkg(gitOpts, opts)
  1033  		assert.Equal(t, err, nil)
  1034  
  1035  		fileBytes, err := os.ReadFile(filepath.Join(testPath, tc.expectFile))
  1036  		assert.Equal(t, err, nil)
  1037  
  1038  		var expectObj map[string]interface{}
  1039  		err = json.Unmarshal(fileBytes, &expectObj)
  1040  		assert.Equal(t, err, nil)
  1041  
  1042  		var gotObj map[string]interface{}
  1043  		err = json.Unmarshal([]byte(result.GetRawJsonResult()), &gotObj)
  1044  		assert.Equal(t, err, nil)
  1045  
  1046  		assert.Equal(t, gotObj, expectObj)
  1047  	}
  1048  }
  1049  
  1050  func TestUpdateWithNoSumCheck(t *testing.T) {
  1051  	pkgPath := getTestDir("test_update_no_sum_check")
  1052  	kpmcli, err := NewKpmClient()
  1053  	assert.Equal(t, err, nil)
  1054  
  1055  	var buf bytes.Buffer
  1056  	kpmcli.SetLogWriter(&buf)
  1057  
  1058  	kpmcli.SetNoSumCheck(true)
  1059  	kclPkg, err := kpmcli.LoadPkgFromPath(pkgPath)
  1060  	assert.Equal(t, err, nil)
  1061  
  1062  	err = kpmcli.UpdateDeps(kclPkg)
  1063  	assert.Equal(t, err, nil)
  1064  	assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), false)
  1065  	assert.Equal(t, buf.String(), "")
  1066  
  1067  	kpmcli.SetNoSumCheck(false)
  1068  	kclPkg, err = kpmcli.LoadPkgFromPath(pkgPath)
  1069  	assert.Equal(t, err, nil)
  1070  
  1071  	err = kpmcli.UpdateDeps(kclPkg)
  1072  	assert.Equal(t, err, nil)
  1073  	assert.Equal(t, utils.DirExists(filepath.Join(pkgPath, "kcl.mod.lock")), true)
  1074  	assert.Equal(t, buf.String(), "adding 'helloworld' with version '0.1.1'\ndownloading 'kcl-lang/helloworld:0.1.1' from 'ghcr.io/kcl-lang/helloworld:0.1.1'\n")
  1075  
  1076  	defer func() {
  1077  		_ = os.Remove(filepath.Join(pkgPath, "kcl.mod.lock"))
  1078  	}()
  1079  }
  1080  
  1081  func TestAddWithDiffVersionNoSumCheck(t *testing.T) {
  1082  	pkgPath := getTestDir("test_add_diff_version")
  1083  
  1084  	pkgWithSumCheckPath := filepath.Join(pkgPath, "no_sum_check")
  1085  	pkgWithSumCheckPathModBak := filepath.Join(pkgWithSumCheckPath, "kcl.mod.bak")
  1086  	pkgWithSumCheckPathMod := filepath.Join(pkgWithSumCheckPath, "kcl.mod")
  1087  	pkgWithSumCheckPathModExpect := filepath.Join(pkgWithSumCheckPath, "kcl.mod.expect")
  1088  	pkgWithSumCheckPathModLock := filepath.Join(pkgWithSumCheckPath, "kcl.mod.lock")
  1089  
  1090  	err := copy.Copy(pkgWithSumCheckPathModBak, pkgWithSumCheckPathMod)
  1091  	assert.Equal(t, err, nil)
  1092  
  1093  	kpmcli, err := NewKpmClient()
  1094  	assert.Equal(t, err, nil)
  1095  	kclPkg, err := kpmcli.LoadPkgFromPath(pkgWithSumCheckPath)
  1096  	assert.Equal(t, err, nil)
  1097  
  1098  	opts := opt.AddOptions{
  1099  		LocalPath: pkgPath,
  1100  		RegistryOpts: opt.RegistryOptions{
  1101  			Oci: &opt.OciOptions{
  1102  				Reg:     "ghcr.io",
  1103  				Repo:    "kcl-lang",
  1104  				PkgName: "helloworld",
  1105  				Tag:     "0.1.1",
  1106  			},
  1107  		},
  1108  		NoSumCheck: true,
  1109  	}
  1110  
  1111  	_, err = kpmcli.AddDepWithOpts(kclPkg, &opts)
  1112  	assert.Equal(t, err, nil)
  1113  	assert.Equal(t, utils.DirExists(pkgWithSumCheckPathModLock), false)
  1114  
  1115  	modContent, err := os.ReadFile(pkgWithSumCheckPathMod)
  1116  	modContentStr := strings.ReplaceAll(string(modContent), "\r\n", "")
  1117  	modContentStr = strings.ReplaceAll(string(modContentStr), "\n", "")
  1118  	assert.Equal(t, err, nil)
  1119  	modExpectContent, err := os.ReadFile(pkgWithSumCheckPathModExpect)
  1120  	modExpectContentStr := strings.ReplaceAll(string(modExpectContent), "\r\n", "")
  1121  	modExpectContentStr = strings.ReplaceAll(modExpectContentStr, "\n", "")
  1122  	assert.Equal(t, err, nil)
  1123  	assert.Equal(t, modContentStr, modExpectContentStr)
  1124  
  1125  	opts.NoSumCheck = false
  1126  	_, err = kpmcli.AddDepWithOpts(kclPkg, &opts)
  1127  	assert.Equal(t, err, nil)
  1128  	assert.Equal(t, utils.DirExists(pkgWithSumCheckPathModLock), true)
  1129  	modContent, err = os.ReadFile(pkgWithSumCheckPathMod)
  1130  	modContentStr = strings.ReplaceAll(string(modContent), "\r\n", "")
  1131  	modContentStr = strings.ReplaceAll(modContentStr, "\n", "")
  1132  	assert.Equal(t, err, nil)
  1133  	assert.Equal(t, modContentStr, modExpectContentStr)
  1134  
  1135  	defer func() {
  1136  		_ = os.Remove(pkgWithSumCheckPathMod)
  1137  		_ = os.Remove(pkgWithSumCheckPathModLock)
  1138  	}()
  1139  }
  1140  
  1141  func TestAddWithDiffVersionWithSumCheck(t *testing.T) {
  1142  	pkgPath := getTestDir("test_add_diff_version")
  1143  
  1144  	pkgWithSumCheckPath := filepath.Join(pkgPath, "with_sum_check")
  1145  	pkgWithSumCheckPathModBak := filepath.Join(pkgWithSumCheckPath, "kcl.mod.bak")
  1146  	pkgWithSumCheckPathMod := filepath.Join(pkgWithSumCheckPath, "kcl.mod")
  1147  	pkgWithSumCheckPathModExpect := filepath.Join(pkgWithSumCheckPath, "kcl.mod.expect")
  1148  	pkgWithSumCheckPathModLock := filepath.Join(pkgWithSumCheckPath, "kcl.mod.lock")
  1149  	pkgWithSumCheckPathModLockBak := filepath.Join(pkgWithSumCheckPath, "kcl.mod.lock.bak")
  1150  	pkgWithSumCheckPathModLockExpect := filepath.Join(pkgWithSumCheckPath, "kcl.mod.lock.expect")
  1151  
  1152  	err := copy.Copy(pkgWithSumCheckPathModBak, pkgWithSumCheckPathMod)
  1153  	assert.Equal(t, err, nil)
  1154  	err = copy.Copy(pkgWithSumCheckPathModLockBak, pkgWithSumCheckPathModLock)
  1155  	assert.Equal(t, err, nil)
  1156  
  1157  	kpmcli, err := NewKpmClient()
  1158  	assert.Equal(t, err, nil)
  1159  	kclPkg, err := kpmcli.LoadPkgFromPath(pkgWithSumCheckPath)
  1160  	assert.Equal(t, err, nil)
  1161  
  1162  	opts := opt.AddOptions{
  1163  		LocalPath: pkgPath,
  1164  		RegistryOpts: opt.RegistryOptions{
  1165  			Oci: &opt.OciOptions{
  1166  				Reg:     "ghcr.io",
  1167  				Repo:    "kcl-lang",
  1168  				PkgName: "helloworld",
  1169  				Tag:     "0.1.1",
  1170  			},
  1171  		},
  1172  	}
  1173  
  1174  	_, err = kpmcli.AddDepWithOpts(kclPkg, &opts)
  1175  	assert.Equal(t, err, nil)
  1176  
  1177  	modContent, err := os.ReadFile(pkgWithSumCheckPathMod)
  1178  	modContentStr := strings.ReplaceAll(string(modContent), "\r\n", "")
  1179  	modContentStr = strings.ReplaceAll(modContentStr, "\n", "")
  1180  	assert.Equal(t, err, nil)
  1181  
  1182  	modExpectContent, err := os.ReadFile(pkgWithSumCheckPathModExpect)
  1183  	modExpectContentStr := strings.ReplaceAll(string(modExpectContent), "\r\n", "")
  1184  	modExpectContentStr = strings.ReplaceAll(modExpectContentStr, "\n", "")
  1185  
  1186  	assert.Equal(t, err, nil)
  1187  	assert.Equal(t, modContentStr, modExpectContentStr)
  1188  
  1189  	modLockContent, err := os.ReadFile(pkgWithSumCheckPathModLock)
  1190  	modLockContentStr := strings.ReplaceAll(string(modLockContent), "\r\n", "")
  1191  	modLockContentStr = strings.ReplaceAll(modLockContentStr, "\n", "")
  1192  	assert.Equal(t, err, nil)
  1193  	modLockExpectContent, err := os.ReadFile(pkgWithSumCheckPathModLockExpect)
  1194  	modLockExpectContentStr := strings.ReplaceAll(string(modLockExpectContent), "\r\n", "")
  1195  	modLockExpectContentStr = strings.ReplaceAll(modLockExpectContentStr, "\n", "")
  1196  	assert.Equal(t, err, nil)
  1197  	assert.Equal(t, modLockContentStr, modLockExpectContentStr)
  1198  
  1199  	defer func() {
  1200  		_ = os.Remove(pkgWithSumCheckPathMod)
  1201  		_ = os.Remove(pkgWithSumCheckPathModLock)
  1202  	}()
  1203  }
  1204  
  1205  func TestAddWithGitCommit(t *testing.T) {
  1206  	pkgPath := getTestDir("add_with_git_commit")
  1207  
  1208  	testPkgPath := ""
  1209  	if runtime.GOOS == "windows" {
  1210  		testPkgPath = filepath.Join(pkgPath, "test_pkg_win")
  1211  	} else {
  1212  		testPkgPath = filepath.Join(pkgPath, "test_pkg")
  1213  	}
  1214  
  1215  	testPkgPathModBak := filepath.Join(testPkgPath, "kcl.mod.bak")
  1216  	testPkgPathMod := filepath.Join(testPkgPath, "kcl.mod")
  1217  	testPkgPathModExpect := filepath.Join(testPkgPath, "kcl.mod.expect")
  1218  	testPkgPathModLock := filepath.Join(testPkgPath, "kcl.mod.lock")
  1219  	testPkgPathModLockBak := filepath.Join(testPkgPath, "kcl.mod.lock.bak")
  1220  	testPkgPathModLockExpect := filepath.Join(testPkgPath, "kcl.mod.lock.expect")
  1221  
  1222  	err := copy.Copy(testPkgPathModBak, testPkgPathMod)
  1223  	assert.Equal(t, err, nil)
  1224  	err = copy.Copy(testPkgPathModLockBak, testPkgPathModLock)
  1225  	assert.Equal(t, err, nil)
  1226  
  1227  	kpmcli, err := NewKpmClient()
  1228  	assert.Equal(t, err, nil)
  1229  	kclPkg, err := kpmcli.LoadPkgFromPath(testPkgPath)
  1230  	assert.Equal(t, err, nil)
  1231  
  1232  	opts := opt.AddOptions{
  1233  		LocalPath: testPkgPath,
  1234  		RegistryOpts: opt.RegistryOptions{
  1235  			Git: &opt.GitOptions{
  1236  				Url:    "https://github.com/KusionStack/catalog.git",
  1237  				Commit: "a29e3db",
  1238  			},
  1239  		},
  1240  	}
  1241  	kpmcli.SetLogWriter(nil)
  1242  	_, err = kpmcli.AddDepWithOpts(kclPkg, &opts)
  1243  
  1244  	assert.Equal(t, err, nil)
  1245  
  1246  	modContent, err := os.ReadFile(testPkgPathMod)
  1247  	modContentStr := strings.ReplaceAll(string(modContent), "\r\n", "")
  1248  	modContentStr = strings.ReplaceAll(modContentStr, "\n", "")
  1249  	assert.Equal(t, err, nil)
  1250  
  1251  	modExpectContent, err := os.ReadFile(testPkgPathModExpect)
  1252  	modExpectContentStr := strings.ReplaceAll(string(modExpectContent), "\r\n", "")
  1253  	modExpectContentStr = strings.ReplaceAll(modExpectContentStr, "\n", "")
  1254  
  1255  	assert.Equal(t, err, nil)
  1256  	assert.Equal(t, modContentStr, modExpectContentStr)
  1257  
  1258  	modLockContent, err := os.ReadFile(testPkgPathModLock)
  1259  	modLockContentStr := strings.ReplaceAll(string(modLockContent), "\r\n", "")
  1260  	modLockContentStr = strings.ReplaceAll(modLockContentStr, "\n", "")
  1261  	assert.Equal(t, err, nil)
  1262  	modLockExpectContent, err := os.ReadFile(testPkgPathModLockExpect)
  1263  	modLockExpectContentStr := strings.ReplaceAll(string(modLockExpectContent), "\r\n", "")
  1264  	modLockExpectContentStr = strings.ReplaceAll(modLockExpectContentStr, "\n", "")
  1265  	assert.Equal(t, err, nil)
  1266  	assert.Equal(t, modLockContentStr, modLockExpectContentStr)
  1267  
  1268  	defer func() {
  1269  		_ = os.Remove(testPkgPathMod)
  1270  		_ = os.Remove(testPkgPathModLock)
  1271  	}()
  1272  }