github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/modules/modules_test.go (about)

     1  package modules
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"strings"
     7  	"testing"
     8  
     9  	_ "github.com/lmorg/murex/builtins/core/structs"
    10  	"github.com/lmorg/murex/config/profile"
    11  	"github.com/lmorg/murex/lang"
    12  	"github.com/lmorg/murex/test/count"
    13  	"github.com/lmorg/murex/utils/consts"
    14  )
    15  
    16  var (
    17  	// Test Package
    18  
    19  	testPackage = "TestPackage"
    20  
    21  	testJsonPackage = profile.Package{
    22  		Name:    testPackage,
    23  		Version: "0.0",
    24  	}
    25  
    26  	// Test Module 2
    27  
    28  	testModule1 = "TestModule1"
    29  
    30  	testJsonModule1 = profile.Module{
    31  		Name:    testModule1,
    32  		Summary: "ūnus",
    33  		Version: "1.0",
    34  		Source:  "one.mx",
    35  		Dependencies: profile.Dependencies{
    36  			Required: []string{
    37  				"go",
    38  			},
    39  			Platform: []string{
    40  				"any",
    41  			},
    42  		},
    43  	}
    44  
    45  	testFunction1 = "modules.testMxSource1"
    46  	testMxSource1 = "function " + testFunction1 + " {}"
    47  
    48  	// Test Module 2
    49  
    50  	testModule2 = "TestModule2"
    51  
    52  	testJsonModule2 = profile.Module{
    53  		Name:    testModule2,
    54  		Summary: "duo",
    55  		Version: "2.0",
    56  		Source:  "two.mx",
    57  		Dependencies: profile.Dependencies{
    58  			Required: []string{
    59  				"go",
    60  			},
    61  			Platform: []string{
    62  				"any",
    63  			},
    64  		},
    65  	}
    66  
    67  	testFunction2 = "modules.testMxSource2"
    68  	testMxSource2 = "function " + testFunction2 + " {}"
    69  
    70  	testJsonModules = []profile.Module{
    71  		testJsonModule1,
    72  		testJsonModule2,
    73  	}
    74  )
    75  
    76  func testModulesWriteBytes(t *testing.T, name, path string, contents []byte) {
    77  	t.Helper()
    78  
    79  	file, err := os.OpenFile(path+name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0640)
    80  	if err != nil {
    81  		t.Fatalf("Error initializing %s: %s", name, err.Error())
    82  	}
    83  
    84  	_, err = file.Write(contents)
    85  	if err != nil {
    86  		t.Fatalf("Error initializing %s: %s", name, err.Error())
    87  	}
    88  
    89  	if file.Close() != nil {
    90  		t.Fatalf("Error closing %s: %s", name, err.Error())
    91  	}
    92  }
    93  
    94  func testModulesWriteStruct(t *testing.T, name, path string, v interface{}) {
    95  	t.Helper()
    96  
    97  	b, err := json.MarshalIndent(v, "", "    ")
    98  	if err != nil {
    99  		t.Fatalf("Error initializing %s: %s", name, err.Error())
   100  	}
   101  
   102  	testModulesWriteBytes(t, name, path, b)
   103  }
   104  
   105  func vToString(t *testing.T, v interface{}) string {
   106  	t.Helper()
   107  
   108  	b, err := json.MarshalIndent(v, "", "    ")
   109  	if err != nil {
   110  		t.Fatalf("Error creating JSON from %T: %s", v, err.Error())
   111  	}
   112  	return string(b)
   113  }
   114  
   115  // TestModulesAndCustomPaths tests a range of functionality from the env var
   116  // custom paths to a lot of the code surrounding loading, enabling and disabling
   117  // modules and packages
   118  func TestModulesAndCustomPaths(t *testing.T) {
   119  	var (
   120  		preloadFileName = "preload_TestModulesAndCustomPaths.mx"
   121  		modulesPathName = "modules_TestModulesAndCustomPaths.d/"
   122  		profileFileName = "profile_TestModulesAndCustomPaths.mx"
   123  	)
   124  
   125  	path := t.TempDir()
   126  
   127  	// get running settings
   128  
   129  	bakPreload := os.Getenv(profile.PreloadEnvVar)
   130  	bakModule := os.Getenv(profile.ModuleEnvVar)
   131  	bakProfile := os.Getenv(profile.ProfileEnvVar)
   132  
   133  	defer func() {
   134  		if err := os.Setenv(profile.PreloadEnvVar, bakPreload); err != nil {
   135  			t.Errorf("Unable to restore env var settings: '%s' to '%s'", profile.PreloadEnvVar, bakPreload)
   136  		}
   137  
   138  		if err := os.Setenv(profile.ModuleEnvVar, bakModule); err != nil {
   139  			t.Errorf("Unable to restore env var settings: '%s' to '%s'", profile.ModuleEnvVar, bakModule)
   140  		}
   141  
   142  		if err := os.Setenv(profile.ProfileEnvVar, bakProfile); err != nil {
   143  			t.Errorf("Unable to restore env var settings: '%s' to '%s'", profile.ProfileEnvVar, bakProfile)
   144  		}
   145  	}()
   146  
   147  	// set env vars
   148  
   149  	if err := os.Setenv(profile.PreloadEnvVar, path+preloadFileName); err != nil {
   150  		t.Errorf("Unable to set env var %s: %s", profile.PreloadEnvVar, err.Error())
   151  	}
   152  
   153  	if err := os.Setenv(profile.ModuleEnvVar, path+modulesPathName); err != nil {
   154  		t.Errorf("Unable to set env var %s: %s", profile.ModuleEnvVar, err.Error())
   155  	}
   156  
   157  	if err := os.Setenv(profile.ProfileEnvVar, path+profileFileName); err != nil {
   158  		t.Errorf("Unable to set env var %s: %s", profile.ProfileEnvVar, err.Error())
   159  	}
   160  
   161  	// initialize empty directory structures
   162  
   163  	lang.InitEnv()
   164  	profile.Execute(profile.F_MODULES)
   165  
   166  	// initialize test package
   167  
   168  	packagePath := path + modulesPathName + consts.PathSlash + "TestPackage" + consts.PathSlash
   169  	if err := os.Mkdir(packagePath, 0777); err != nil && !strings.Contains(err.Error(), "file exists") {
   170  		t.Fatalf("Unable to initialize test package: Cannot create dir: %s", err.Error())
   171  	}
   172  
   173  	testModulesWriteStruct(t, "package.json", packagePath, testJsonPackage)
   174  	testModulesWriteStruct(t, "module.json", packagePath, testJsonModules)
   175  	testModulesWriteBytes(t, "one.mx", packagePath, []byte(testMxSource1))
   176  	testModulesWriteBytes(t, "two.mx", packagePath, []byte(testMxSource2))
   177  
   178  	// import new packages
   179  
   180  	count.Tests(t, 1) // importing from non-standard location
   181  	profile.Execute(profile.F_MODULES)
   182  
   183  	if !lang.MxFunctions.Exists(testFunction1) || !lang.MxFunctions.Exists(testFunction2) {
   184  		t.Fatalf("test functions were not imported from test package. Reason: unknown\n%s\nTry deleting '%s' and then rerun",
   185  			vToString(t, lang.MxFunctions.Dump()), path+modulesPathName+consts.PathSlash)
   186  	}
   187  
   188  	// run tests
   189  
   190  	count.Tests(t, 2)
   191  	list, err := listModulesLoadNotLoad(lang.ShellProcess, true)
   192  	if err != nil {
   193  		t.Fatalf("Error in listModulesLoadNotLoad(true): %s", err.Error())
   194  	}
   195  	if len(list) != 2 || list[testPackage+"/"+testModule1] == "" || list[testPackage+"/"+testModule2] == "" {
   196  		t.Fatalf("listModulesLoadNotLoad(true) has returned an unexpected list:\n%s", vToString(t, list))
   197  	}
   198  
   199  	count.Tests(t, 2)
   200  	list, err = listModulesEnDis(lang.ShellProcess, true)
   201  	if err != nil {
   202  		t.Fatalf("Error in listModulesLoadNotLoad(true): %s", err.Error())
   203  	}
   204  	if len(list) != 3 || list[testPackage] == "" ||
   205  		list[testPackage+"/"+testModule1] == "" ||
   206  		list[testPackage+"/"+testModule2] == "" {
   207  		t.Fatalf("listModulesLoadNotLoad(true) has returned an unexpected list:\n%s", vToString(t, list))
   208  	}
   209  
   210  	count.Tests(t, 3)
   211  	var disabled []string
   212  	err = profile.ReadJson(profile.ModulePath()+profile.DisabledFile, &disabled)
   213  	if err != nil {
   214  		t.Fatalf("profile.ReadJson() err: %s", err.Error())
   215  	}
   216  
   217  	err = disableMod(testPackage+"/"+testModule1, &disabled)
   218  	if err != nil {
   219  		t.Fatalf("disableMod() err: %s", err.Error())
   220  	}
   221  	err = writeDisabled(&disabled)
   222  	if err != nil {
   223  		t.Fatalf("writeDisabled() err: %s", err.Error())
   224  	}
   225  
   226  	count.Tests(t, 2)
   227  	list, err = listModulesEnDis(lang.ShellProcess, false)
   228  	if err != nil {
   229  		t.Fatalf("Error in listModulesEnDis(true): %s", err.Error())
   230  	}
   231  	if len(list) != 1 || list[testPackage] != "" ||
   232  		list[testPackage+"/"+testModule1] == "" ||
   233  		list[testPackage+"/"+testModule2] != "" {
   234  		t.Fatalf("listModulesEnDis(true) has returned an unexpected list:\n%s", vToString(t, list))
   235  	}
   236  
   237  	count.Tests(t, 3)
   238  	err = profile.ReadJson(profile.ModulePath()+profile.DisabledFile, &disabled)
   239  	if err != nil {
   240  		t.Fatalf("profile.ReadJson() err: %s", err.Error())
   241  	}
   242  
   243  	disabled, err = enableMod(testPackage+"/"+testModule1, disabled)
   244  	if err != nil {
   245  		t.Fatalf("enableMod() err: %s", err.Error())
   246  	}
   247  	err = writeDisabled(&disabled)
   248  	if err != nil {
   249  		t.Fatalf("writeDisabled() err: %s", err.Error())
   250  	}
   251  
   252  	count.Tests(t, 2)
   253  	list, err = listModulesEnDis(lang.ShellProcess, true)
   254  	if err != nil {
   255  		t.Fatalf("Error in listModulesEnDis(true): %s", err.Error())
   256  	}
   257  	if len(list) != 3 || list[testPackage] == "" ||
   258  		list[testPackage+"/"+testModule1] == "" ||
   259  		list[testPackage+"/"+testModule2] == "" {
   260  		t.Fatalf("listModulesEnDis(true) has returned an unexpected list:\n%s", vToString(t, list))
   261  	}
   262  
   263  }