package download
import (
"os"
"path/filepath"
"testing"
)
func writeFile(t *testing.T, path, content string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
}
func TestCombineDirTreesNonexistentSrcIsNoop(t *testing.T) {
dest := t.TempDir()
if err := combineDirTrees(filepath.Join(t.TempDir(), "does-not-exist"), dest); err != nil {
t.Fatalf("combineDirTrees with a nonexistent src returned an error: %v", err)
}
}
func TestCombineDirTreesRenamesWholesaleWhenDestMissing(t *testing.T) {
root := t.TempDir()
src := filepath.Join(root, "src")
dest := filepath.Join(root, "nested", "dest")
writeFile(t, filepath.Join(src, "file.txt"), "hello")
if err := combineDirTrees(src, dest); err != nil {
t.Fatal(err)
}
if _, err := os.ReadFile(filepath.Join(dest, "file.txt")); err != nil {
t.Errorf("expected %s/file.txt to exist after combine: %v", dest, err)
}
if isDir(src) {
t.Error("src should have been moved (renamed), not copied")
}
}
func TestCombineDirTreesMergesNewSubdir(t *testing.T) {
root := t.TempDir()
src, dest := filepath.Join(root, "src"), filepath.Join(root, "dest")
writeFile(t, filepath.Join(src, "NewDir", "a.txt"), "a")
writeFile(t, filepath.Join(dest, "Existing.txt"), "keep me")
if err := combineDirTrees(src, dest); err != nil {
t.Fatal(err)
}
if _, err := os.ReadFile(filepath.Join(dest, "NewDir", "a.txt")); err != nil {
t.Errorf("expected merged NewDir/a.txt: %v", err)
}
if _, err := os.ReadFile(filepath.Join(dest, "Existing.txt")); err != nil {
t.Errorf("pre-existing dest file was lost: %v", err)
}
}
func TestCombineDirTreesMergesCaseInsensitiveCollision(t *testing.T) {
root := t.TempDir()
src, dest := filepath.Join(root, "src"), filepath.Join(root, "dest")
// src has "Include" (capital I), dest already has "include" (lowercase) -
// this is exactly the MSVC/WinSDK casing-inconsistency scenario the
// function's doc comment describes.
writeFile(t, filepath.Join(src, "Include", "new.h"), "new")
writeFile(t, filepath.Join(dest, "include", "old.h"), "old")
if err := combineDirTrees(src, dest); err != nil {
t.Fatal(err)
}
if _, err := os.ReadFile(filepath.Join(dest, "include", "new.h")); err != nil {
t.Errorf("new.h should have merged into the existing lowercase 'include' dir: %v", err)
}
if _, err := os.ReadFile(filepath.Join(dest, "include", "old.h")); err != nil {
t.Errorf("old.h should still be there: %v", err)
}
if isDir(filepath.Join(dest, "Include")) {
t.Error("a separate capital-I 'Include' dir should not have been created")
}
}
func TestCombineDirTreesRecursesIntoExactNameMatch(t *testing.T) {
root := t.TempDir()
src, dest := filepath.Join(root, "src"), filepath.Join(root, "dest")
writeFile(t, filepath.Join(src, "lib", "x64", "new.lib"), "new")
writeFile(t, filepath.Join(dest, "lib", "x64", "old.lib"), "old")
if err := combineDirTrees(src, dest); err != nil {
t.Fatal(err)
}
for _, f := range []string{"new.lib", "old.lib"} {
if _, err := os.ReadFile(filepath.Join(dest, "lib", "x64", f)); err != nil {
t.Errorf("expected lib/x64/%s to survive the merge: %v", f, err)
}
}
}
func TestCopyRedirectedAssembliesNoConfigIsNoop(t *testing.T) {
dir := t.TempDir()
app := filepath.Join(dir, "MSBuild.exe")
if err := CopyRedirectedAssemblies(app); err != nil {
t.Fatalf("with no .config file present, expected no error, got: %v", err)
}
}
func TestCopyRedirectedAssembliesCopiesReferencedDLL(t *testing.T) {
dir := t.TempDir()
app := filepath.Join(dir, "MSBuild.exe")
writeFile(t, app+".config", `
`)
writeFile(t, filepath.Join(dir, "amd64", "Some.Assembly.dll"), "binary-content")
if err := CopyRedirectedAssemblies(app); err != nil {
t.Fatal(err)
}
got, err := os.ReadFile(filepath.Join(dir, "Some.Assembly.dll"))
if err != nil {
t.Fatalf("expected Some.Assembly.dll copied next to MSBuild.exe: %v", err)
}
if string(got) != "binary-content" {
t.Errorf("copied file content = %q, want %q", got, "binary-content")
}
}
func TestCopyRedirectedAssembliesSkipsMissingTarget(t *testing.T) {
dir := t.TempDir()
app := filepath.Join(dir, "MSBuild.exe")
writeFile(t, app+".config", `
`)
if err := CopyRedirectedAssemblies(app); err != nil {
t.Fatalf("a redirect pointing at a nonexistent file should be silently skipped, got: %v", err)
}
}