Browse Source

Merge pull request #4037 from Kelimion/symlink_test

Allow symlink test to work irrespective of git settings.
Jeroen van Rijn 1 year ago
parent
commit
a7fe9eec73
4 changed files with 51 additions and 16 deletions
  1. 4 0
      core/sys/windows/kernel32.odin
  2. 6 0
      core/sys/windows/types.odin
  3. 0 1
      tests/core/os/dir/alink.txt
  4. 41 15
      tests/core/os/os.odin

+ 4 - 0
core/sys/windows/kernel32.odin

@@ -85,6 +85,10 @@ foreign kernel32 {
 	                        lpTargetFileName: LPCWSTR,
 	                        lpSecurityAttributes: LPSECURITY_ATTRIBUTES) -> BOOL ---
 
+	CreateSymbolicLinkW :: proc(lpSymlinkFileName: LPCWSTR,
+	                            lpTargetFileName:  LPCWSTR,
+	                            dwFlags:           SYMBOLIC_LINK_FLAGS) -> BOOLEAN ---
+
 	GetFileInformationByHandleEx :: proc(hFile: HANDLE,
 	                                     fileInfoClass: FILE_INFO_BY_HANDLE_CLASS,
 	                                     lpFileInformation: LPVOID,

+ 6 - 0
core/sys/windows/types.odin

@@ -1276,6 +1276,12 @@ FOF_NO_UI                 :: (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI |
 
 FILEOP_FLAGS :: WORD
 
+SYMBOLIC_LINK_FLAG :: enum DWORD {
+	DIRECTORY                = 0,
+	ALLOW_UNPRIVILGED_CREATE = 1,
+}
+SYMBOLIC_LINK_FLAGS :: bit_set[SYMBOLIC_LINK_FLAG; DWORD]
+
 DEVMODEW :: struct {
 	dmDeviceName:   [32]wchar_t,
 	dmSpecVersion:   WORD,

+ 0 - 1
tests/core/os/dir/alink.txt

@@ -1 +0,0 @@
-./a.txt

+ 41 - 15
tests/core/os/os.odin

@@ -1,12 +1,35 @@
-package tests_core_os
+package test_core_os
 
+import "core:c/libc"
+import win32 "core:sys/windows"
 import "core:os"
 import "core:slice"
-
 import "core:testing"
+import "core:log"
+
+_ :: libc
+_ :: win32
 
 @(test)
 read_dir :: proc(t: ^testing.T) {
+	when ODIN_OS == .Windows {
+		link    := win32.utf8_to_wstring(#directory + "dir/alink.txt")
+		target  := win32.utf8_to_wstring(#directory + "dir/a.txt")
+		sym_err := win32.CreateSymbolicLinkW(link, target, {.ALLOW_UNPRIVILGED_CREATE})
+
+		if !sym_err {
+			log.infof("Unable to create symlink, skipping test. Error: %v", win32.GetLastError())
+			return
+		}
+	} else {
+		sym_err := libc.system("ln -s " + #directory + "dir/a.txt " + #directory + "dir/alink.txt")
+		if sym_err != 0 {
+			log.infof("Unable to create symlink, skipping test. Error: %v", sym_err)
+			return
+		}
+	}
+	defer os.remove(#directory + "dir/alink.txt")
+
 	fd, err := os.open(#directory + "/dir")
 	testing.expect_value(t, err, nil)
 	defer os.close(fd)
@@ -19,17 +42,20 @@ read_dir :: proc(t: ^testing.T) {
 
 	testing.expect_value(t, len(dir), 3)
 
-	testing.expect_value(t, dir[0].name, "alink.txt")
-	testing.expect(t, !dir[0].is_dir, "is a directory")
-	when ODIN_OS == .Windows {
-		testing.expect(t, dir[0].mode & os.File_Mode_Sym_Link != 0, "not a symlink")
-	} else {
-		testing.expect(t, os.S_ISLNK(auto_cast dir[0].mode), "not a symlink")
+	if len(dir) > 0 {
+		testing.expect_value(t, dir[0].name, "alink.txt")
+		testing.expect(t, !dir[0].is_dir, "is a directory")
+		when ODIN_OS == .Windows {
+			testing.expect(t, dir[0].mode & os.File_Mode_Sym_Link != 0, "not a symlink")
+		} else {
+			testing.expect(t, os.S_ISLNK(auto_cast dir[0].mode), "not a symlink")
+		}
 	}
-
-	testing.expect_value(t, dir[1].name, "b.txt")
-
-	testing.expect_value(t, dir[2].name, "sub")
-	testing.expect(t, dir[2].is_dir, "is not a directory")
-}
-
+	if len(dir) > 1 {
+		testing.expect_value(t, dir[1].name, "b.txt")
+	}
+	if len(dir) > 2 {
+		testing.expect_value(t, dir[2].name, "sub")
+		testing.expect(t, dir[2].is_dir, "is not a directory")
+	}
+}