1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.buildcache;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.nio.charset.StandardCharsets;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.attribute.PosixFilePermission;
27 import java.nio.file.attribute.PosixFilePermissions;
28 import java.util.Arrays;
29 import java.util.Set;
30
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.io.TempDir;
33
34 import static org.junit.jupiter.api.Assertions.assertFalse;
35 import static org.junit.jupiter.api.Assertions.assertTrue;
36
37
38
39
40
41
42 class CacheUtilsPermissionsTest {
43
44 @TempDir
45 Path tempDir;
46
47
48
49
50
51
52 @Test
53 void testPermissionsAffectFileHashWhenEnabled() throws IOException {
54
55 if (!tempDir.getFileSystem().supportedFileAttributeViews().contains("posix")) {
56 return;
57 }
58
59
60 Path sourceDir1 = tempDir.resolve("source1");
61 Files.createDirectories(sourceDir1);
62 Path file1 = sourceDir1.resolve("script.sh");
63 writeString(file1, "#!/bin/bash\necho hello");
64
65
66 Set<PosixFilePermission> execPermissions = PosixFilePermissions.fromString("rwxr-xr-x");
67 Files.setPosixFilePermissions(file1, execPermissions);
68
69
70 Path sourceDir2 = tempDir.resolve("source2");
71 Files.createDirectories(sourceDir2);
72 Path file2 = sourceDir2.resolve("script.sh");
73 writeString(file2, "#!/bin/bash\necho hello");
74
75
76 Set<PosixFilePermission> normalPermissions = PosixFilePermissions.fromString("rw-r--r--");
77 Files.setPosixFilePermissions(file2, normalPermissions);
78
79
80 Path zip1 = tempDir.resolve("cache1.zip");
81 Path zip2 = tempDir.resolve("cache2.zip");
82 CacheUtils.zip(sourceDir1, zip1, "*", true);
83 CacheUtils.zip(sourceDir2, zip2, "*", true);
84
85
86 byte[] hash1 = Files.readAllBytes(zip1);
87 byte[] hash2 = Files.readAllBytes(zip2);
88
89 boolean hashesAreDifferent = !Arrays.equals(hash1, hash2);
90 assertTrue(
91 hashesAreDifferent,
92 "ZIP files with same content but different permissions should have different hashes "
93 + "when preservePermissions=true. This ensures cache invalidation when permissions change "
94 + "(executable vs non-executable files).");
95 }
96
97
98
99
100
101
102 @Test
103 void testPermissionsDoNotAffectHashWhenDisabled() throws IOException {
104
105 if (!tempDir.getFileSystem().supportedFileAttributeViews().contains("posix")) {
106 return;
107 }
108
109
110 Path sourceDir1 = tempDir.resolve("source1");
111 Files.createDirectories(sourceDir1);
112 Path file1 = sourceDir1.resolve("script.sh");
113 writeString(file1, "#!/bin/bash\necho hello");
114
115
116 Set<PosixFilePermission> execPermissions = PosixFilePermissions.fromString("rwxr-xr-x");
117 Files.setPosixFilePermissions(file1, execPermissions);
118
119
120 Path sourceDir2 = tempDir.resolve("source2");
121 Files.createDirectories(sourceDir2);
122 Path file2 = sourceDir2.resolve("script.sh");
123 writeString(file2, "#!/bin/bash\necho hello");
124
125
126 Set<PosixFilePermission> normalPermissions = PosixFilePermissions.fromString("rw-r--r--");
127 Files.setPosixFilePermissions(file2, normalPermissions);
128
129
130 Path zip1 = tempDir.resolve("cache1.zip");
131 Path zip2 = tempDir.resolve("cache2.zip");
132 CacheUtils.zip(sourceDir1, zip1, "*", false);
133 CacheUtils.zip(sourceDir2, zip2, "*", false);
134
135
136 Path extractDir1 = tempDir.resolve("extracted1");
137 Path extractDir2 = tempDir.resolve("extracted2");
138 Files.createDirectories(extractDir1);
139 Files.createDirectories(extractDir2);
140 CacheUtils.unzip(zip1, extractDir1, false);
141 CacheUtils.unzip(zip2, extractDir2, false);
142
143 Path extractedFile1 = extractDir1.resolve("script.sh");
144 Path extractedFile2 = extractDir2.resolve("script.sh");
145
146 Set<PosixFilePermission> perms1 = Files.getPosixFilePermissions(extractedFile1);
147 Set<PosixFilePermission> perms2 = Files.getPosixFilePermissions(extractedFile2);
148
149
150
151 assertFalse(
152 perms1.equals(execPermissions) && perms2.equals(normalPermissions),
153 "When preservePermissions=false, original permissions should NOT be preserved. "
154 + "Files should use system default permissions (umask).");
155 }
156
157
158
159
160 private void writeString(Path path, String content) throws IOException {
161 try (OutputStream out = Files.newOutputStream(path)) {
162 out.write(content.getBytes(StandardCharsets.UTF_8));
163 }
164 }
165 }