Skip to content

Commit 787d4a3

Browse files
Check env filters early to avoid FUSE mount errors on DBR (#4506)
## Changes Move env filter check to the beginning of runTest() before creating workspace directories. This prevents "unlinkat: directory not empty" errors on the workspace FUSE mount which seem to happen when there are too many directory creation / deletion. --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
1 parent b18a35b commit 787d4a3

File tree

1 file changed

+48
-33
lines changed

1 file changed

+48
-33
lines changed

acceptance/acceptance_test.go

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,13 @@ func runTest(t *testing.T,
485485
customEnv []string,
486486
envFilters []string,
487487
) {
488+
// Check env filters early, before creating any resources like directories on the file system.
489+
// Creating / deleting too many directories causes this error on the workspace FUSE mount:
490+
// unlinkat <workspace_path>: directory not empty. Thus avoiding unnecessary directory creation
491+
// is important.
492+
testEnv := buildTestEnv(config.Env, customEnv)
493+
checkEnvFilters(t, testEnv, envFilters)
494+
488495
if LogConfig {
489496
configBytes, err := json.MarshalIndent(config, "", " ")
490497
require.NoError(t, err)
@@ -616,38 +623,12 @@ func runTest(t *testing.T,
616623
uniqueCacheDir := filepath.Join(t.TempDir(), ".cache")
617624
cmd.Env = append(cmd.Env, "DATABRICKS_CACHE_DIR="+uniqueCacheDir)
618625

619-
for _, key := range utils.SortedKeys(config.Env) {
620-
if hasKey(customEnv, key) {
621-
// We want EnvMatrix to take precedence.
622-
// Skip rather than relying on cmd.Env order, because this might interfere with replacements and substitutions.
623-
continue
624-
}
625-
cmd.Env = addEnvVar(t, cmd.Env, &repls, key, config.Env[key], config.EnvRepl, false)
626-
}
627-
628-
for _, keyvalue := range customEnv {
629-
items := strings.SplitN(keyvalue, "=", 2)
630-
require.Len(t, items, 2)
631-
key := items[0]
632-
value := items[1]
626+
for _, kv := range testEnv {
627+
key, value, _ := strings.Cut(kv, "=")
633628
// Only add replacement by default if value is part of EnvMatrix with more than 1 option and length is 4 or more chars
634629
// (to avoid matching "yes" and "no" values from template input parameters)
635-
cmd.Env = addEnvVar(t, cmd.Env, &repls, key, value, config.EnvRepl, len(config.EnvMatrix[key]) > 1 && len(value) >= 4)
636-
}
637-
638-
for filterInd, filterEnv := range envFilters {
639-
filterEnvKey := strings.Split(filterEnv, "=")[0]
640-
for ind := range cmd.Env {
641-
// Search backwards, because the latest settings is what is actually applicable.
642-
envPair := cmd.Env[len(cmd.Env)-1-ind]
643-
if strings.Split(envPair, "=")[0] == filterEnvKey {
644-
if envPair == filterEnv {
645-
break
646-
} else {
647-
t.Skipf("Skipping because test environment %s does not match ENVFILTER#%d: %s", envPair, filterInd, filterEnv)
648-
}
649-
}
650-
}
630+
defaultRepl := hasKey(customEnv, key) && len(config.EnvMatrix[key]) > 1 && len(value) >= 4
631+
cmd.Env = addEnvVar(t, cmd.Env, &repls, key, value, config.EnvRepl, defaultRepl)
651632
}
652633

653634
absDir, err := filepath.Abs(dir)
@@ -731,10 +712,44 @@ func runTest(t *testing.T,
731712
}
732713
}
733714

715+
// checkEnvFilters skips the test if any env filter doesn't match testEnv.
716+
func checkEnvFilters(t *testing.T, testEnv, envFilters []string) {
717+
envMap := make(map[string]string, len(testEnv))
718+
for _, kv := range testEnv {
719+
key, value, _ := strings.Cut(kv, "=")
720+
envMap[key] = value
721+
}
722+
for i, filter := range envFilters {
723+
key, expected, _ := strings.Cut(filter, "=")
724+
if actual, ok := envMap[key]; ok && actual != expected {
725+
t.Skipf("Skipping because test environment %s=%s does not match ENVFILTER#%d: %s", key, actual, i, filter)
726+
}
727+
}
728+
}
729+
730+
// buildTestEnv builds the test environment from config.Env and customEnv.
731+
// customEnv (from EnvMatrix) takes precedence over config.Env.
732+
func buildTestEnv(configEnv map[string]string, customEnv []string) []string {
733+
env := make([]string, 0, len(configEnv)+len(customEnv))
734+
735+
// Add config.Env first (but skip keys that exist in customEnv)
736+
for _, key := range utils.SortedKeys(configEnv) {
737+
if hasKey(customEnv, key) {
738+
continue
739+
}
740+
env = append(env, key+"="+configEnv[key])
741+
}
742+
743+
// Add customEnv second (takes precedence)
744+
env = append(env, customEnv...)
745+
746+
return env
747+
}
748+
734749
func hasKey(env []string, key string) bool {
735-
for _, keyvalue := range env {
736-
items := strings.SplitN(keyvalue, "=", 2)
737-
if len(items) == 2 && items[0] == key {
750+
for _, kv := range env {
751+
k, _, ok := strings.Cut(kv, "=")
752+
if ok && k == key {
738753
return true
739754
}
740755
}

0 commit comments

Comments
 (0)