/ components / execd / pkg / runtime / env_test.go
env_test.go
  1  // Copyright 2026 Alibaba Group Holding Ltd.
  2  //
  3  // Licensed under the Apache License, Version 2.0 (the "License");
  4  // you may not use this file except in compliance with the License.
  5  // You may obtain a copy of the License at
  6  //
  7  //     http://www.apache.org/licenses/LICENSE-2.0
  8  //
  9  // Unless required by applicable law or agreed to in writing, software
 10  // distributed under the License is distributed on an "AS IS" BASIS,
 11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  // See the License for the specific language governing permissions and
 13  // limitations under the License.
 14  
 15  package runtime
 16  
 17  import (
 18  	"os"
 19  	"path/filepath"
 20  	"strings"
 21  	"testing"
 22  
 23  	"github.com/stretchr/testify/require"
 24  )
 25  
 26  func TestLoadExtraEnvFromFileUnset(t *testing.T) {
 27  	t.Setenv("EXECD_ENVS", "")
 28  	require.Nil(t, loadExtraEnvFromFile(), "expected nil when EXECD_ENVS unset")
 29  }
 30  
 31  func TestLoadExtraEnvFromFileParsesAndExpands(t *testing.T) {
 32  	dir := t.TempDir()
 33  	envFile := filepath.Join(dir, "env")
 34  
 35  	t.Setenv("EXECD_ENVS", envFile)
 36  	t.Setenv("BASE_DIR", "/opt/base")
 37  
 38  	content := strings.Join([]string{
 39  		"# comment",
 40  		"FOO=bar",
 41  		"PATH=$BASE_DIR/bin",
 42  		"MALFORMED",
 43  		"EMPTY=",
 44  		"",
 45  	}, "\n")
 46  
 47  	require.NoError(t, os.WriteFile(envFile, []byte(content), 0o644))
 48  
 49  	got := loadExtraEnvFromFile()
 50  	require.Len(t, got, 3)
 51  	require.Equal(t, "bar", got["FOO"])
 52  	require.Equal(t, "/opt/base/bin", got["PATH"])
 53  	val, ok := got["EMPTY"]
 54  	require.True(t, ok)
 55  	require.Equal(t, "", val)
 56  }
 57  
 58  func TestLoadExtraEnvFromFileMissingFile(t *testing.T) {
 59  	dir := t.TempDir()
 60  	envFile := filepath.Join(dir, "does-not-exist")
 61  	t.Setenv("EXECD_ENVS", envFile)
 62  
 63  	require.Nil(t, loadExtraEnvFromFile(), "expected nil for missing file")
 64  }
 65  
 66  func TestLoadExtraEnvFromFileSupportsHomePath(t *testing.T) {
 67  	home := t.TempDir()
 68  	t.Setenv("HOME", home)
 69  	t.Setenv("USERPROFILE", home)
 70  
 71  	envFile := filepath.Join(home, "extra.env")
 72  	require.NoError(t, os.WriteFile(envFile, []byte("FOO=bar\n"), 0o644))
 73  	t.Setenv("EXECD_ENVS", "~/extra.env")
 74  
 75  	got := loadExtraEnvFromFile()
 76  	require.Equal(t, "bar", got["FOO"])
 77  }
 78  
 79  func TestMergeEnvsOverlaysExtra(t *testing.T) {
 80  	base := []string{"A=1", "B=2"}
 81  	extra := map[string]string{"B": "override", "C": "3"}
 82  
 83  	merged := mergeEnvs(base, extra)
 84  	got := make(map[string]string)
 85  	for _, kv := range merged {
 86  		parts := strings.SplitN(kv, "=", 2)
 87  		if len(parts) == 2 {
 88  			got[parts[0]] = parts[1]
 89  		}
 90  	}
 91  
 92  	require.Len(t, got, 3)
 93  	require.Equal(t, "1", got["A"])
 94  	require.Equal(t, "override", got["B"])
 95  	require.Equal(t, "3", got["C"])
 96  }
 97  
 98  func TestMergeExtraEnvsMergesAndOverrides(t *testing.T) {
 99  	fromFile := map[string]string{"A": "1", "B": "2"}
100  	fromRequest := map[string]string{"B": "override", "C": "3"}
101  
102  	got := mergeExtraEnvs(fromFile, fromRequest)
103  
104  	require.Len(t, got, 3)
105  	require.Equal(t, "1", got["A"])
106  	require.Equal(t, "override", got["B"])
107  	require.Equal(t, "3", got["C"])
108  }
109  
110  func TestMergeExtraEnvsHandlesNilFromFile(t *testing.T) {
111  	fromRequest := map[string]string{"ONLY": "request"}
112  
113  	got := mergeExtraEnvs(nil, fromRequest)
114  
115  	require.Len(t, got, 1)
116  	require.Equal(t, "request", got["ONLY"])
117  }