1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.internal.transport.http;
11
12 import static org.hamcrest.MatcherAssert.assertThat;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertTrue;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.Writer;
19 import java.net.HttpCookie;
20 import java.net.URL;
21 import java.nio.charset.StandardCharsets;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.nio.file.StandardCopyOption;
25 import java.time.Duration;
26 import java.time.Instant;
27 import java.time.temporal.ChronoUnit;
28 import java.util.Arrays;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Set;
32
33 import org.eclipse.jgit.internal.storage.file.LockFile;
34 import org.eclipse.jgit.util.http.HttpCookiesMatcher;
35 import org.hamcrest.CoreMatchers;
36 import org.junit.Before;
37 import org.junit.Rule;
38 import org.junit.Test;
39 import org.junit.rules.TemporaryFolder;
40
41 public class NetscapeCookieFileTest {
42
43 @Rule
44 public TemporaryFolder folder = new TemporaryFolder();
45
46 private Path tmpFile;
47
48 private URL baseUrl;
49
50
51
52
53 private static final Instant TEST_EXPIRY_DATE = Instant
54 .parse("2030-01-01T12:00:00.000Z");
55
56
57 private static final Instant TEST_DATE = TEST_EXPIRY_DATE.minus(180,
58 ChronoUnit.DAYS);
59
60 @Before
61 public void setUp() throws IOException {
62
63
64 tmpFile = folder.newFile().toPath();
65 baseUrl = new URL("http://domain.com/my/path");
66 }
67
68 @Test
69 public void testMergeCookies() {
70 Set<HttpCookie> cookieSet1 = new LinkedHashSet<>();
71 HttpCookie cookie = new HttpCookie("key1", "valueFromSet1");
72 cookieSet1.add(cookie);
73 cookie = new HttpCookie("key2", "valueFromSet1");
74 cookieSet1.add(cookie);
75
76 Set<HttpCookie> cookieSet2 = new LinkedHashSet<>();
77 cookie = new HttpCookie("key1", "valueFromSet2");
78 cookieSet2.add(cookie);
79 cookie = new HttpCookie("key3", "valueFromSet2");
80 cookieSet2.add(cookie);
81
82 Set<HttpCookie> cookiesExpectedMergedSet = new LinkedHashSet<>();
83 cookie = new HttpCookie("key1", "valueFromSet1");
84 cookiesExpectedMergedSet.add(cookie);
85 cookie = new HttpCookie("key2", "valueFromSet1");
86 cookiesExpectedMergedSet.add(cookie);
87 cookie = new HttpCookie("key3", "valueFromSet2");
88 cookiesExpectedMergedSet.add(cookie);
89
90 assertThat(NetscapeCookieFile.mergeCookies(cookieSet1, cookieSet2),
91 HttpCookiesMatcher.containsInOrder(cookiesExpectedMergedSet));
92
93 assertThat(NetscapeCookieFile.mergeCookies(cookieSet1, null),
94 HttpCookiesMatcher.containsInOrder(cookieSet1));
95 }
96
97 @Test
98 public void testWriteToNewFile() throws IOException {
99 Set<HttpCookie> cookies = new LinkedHashSet<>();
100 cookies.add(new HttpCookie("key1", "value"));
101
102
103 HttpCookie cookie = new HttpCookie("key2", "value");
104 cookie.setSecure(true);
105 cookie.setDomain("mydomain.com");
106 cookie.setPath("/");
107 cookie.setMaxAge(1000);
108 cookies.add(cookie);
109 try (Writer writer = Files.newBufferedWriter(tmpFile,
110 StandardCharsets.US_ASCII)) {
111 NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
112 }
113
114 String expectedExpiration = String
115 .valueOf(TEST_DATE.getEpochSecond() + cookie.getMaxAge());
116
117 assertThat(Files.readAllLines(tmpFile, StandardCharsets.US_ASCII),
118 CoreMatchers
119 .equalTo(Arrays.asList("mydomain.com\tTRUE\t/\tTRUE\t"
120 + expectedExpiration + "\tkey2\tvalue")));
121 }
122
123 @Test
124 public void testWriteToExistingFile() throws IOException {
125 try (InputStream input = this.getClass()
126 .getResourceAsStream("cookies-simple1.txt")) {
127 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
128 }
129
130 Set<HttpCookie> cookies = new LinkedHashSet<>();
131 HttpCookie cookie = new HttpCookie("key2", "value2");
132 cookie.setMaxAge(1000);
133 cookies.add(cookie);
134 try (Writer writer = Files.newBufferedWriter(tmpFile,
135 StandardCharsets.US_ASCII)) {
136 NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
137 }
138 String expectedExpiration = String
139 .valueOf(TEST_DATE.getEpochSecond() + cookie.getMaxAge());
140
141 assertThat(Files.readAllLines(tmpFile, StandardCharsets.US_ASCII),
142 CoreMatchers.equalTo(
143 Arrays.asList("domain.com\tTRUE\t/my/path\tFALSE\t"
144 + expectedExpiration + "\tkey2\tvalue2")));
145 }
146
147 @Test(expected = IOException.class)
148 public void testWriteWhileSomeoneIsHoldingTheLock()
149 throws IllegalArgumentException, IOException, InterruptedException {
150 try (InputStream input = this.getClass()
151 .getResourceAsStream("cookies-simple1.txt")) {
152 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
153 }
154 NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile);
155
156 LockFile lockFile = new LockFile(tmpFile.toFile());
157 try {
158 assertTrue("Could not acquire lock", lockFile.lock());
159 cookieFile.write(baseUrl);
160 } finally {
161 lockFile.unlock();
162 }
163 }
164
165 @Test
166 public void testReadCookieFileWithMilliseconds() throws IOException {
167 try (InputStream input = this.getClass()
168 .getResourceAsStream("cookies-with-milliseconds.txt")) {
169 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
170 }
171 NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile,
172 TEST_DATE);
173 long expectedMaxAge = Duration.between(TEST_DATE, TEST_EXPIRY_DATE)
174 .getSeconds();
175 for (HttpCookie cookie : cookieFile.getCookies(true)) {
176 assertEquals(expectedMaxAge, cookie.getMaxAge());
177 }
178 }
179
180 @Test
181 public void testWriteAfterAnotherJgitProcessModifiedTheFile()
182 throws IOException, InterruptedException {
183 try (InputStream input = this.getClass()
184 .getResourceAsStream("cookies-simple1.txt")) {
185 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
186 }
187 NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile,
188 TEST_DATE);
189 cookieFile.getCookies(true);
190
191 try (InputStream input = this.getClass()
192 .getResourceAsStream("cookies-simple2.txt")) {
193 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
194 }
195
196 cookieFile.write(baseUrl);
197
198 List<String> lines = Files.readAllLines(tmpFile,
199 StandardCharsets.US_ASCII);
200
201 assertEquals("Expected 3 lines", 3, lines.size());
202 assertEquals(
203 "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey1\tvalueFromSimple2",
204 lines.get(0));
205 assertEquals(
206 "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey3\tvalueFromSimple2",
207 lines.get(1));
208 assertEquals(
209 "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey2\tvalueFromSimple1",
210 lines.get(2));
211 }
212
213 @Test
214 public void testWriteAndReadCycle() throws IOException {
215 Set<HttpCookie> cookies = new LinkedHashSet<>();
216
217 HttpCookie cookie = new HttpCookie("key1", "value1");
218 cookie.setPath("/some/path1");
219 cookie.setDomain("some-domain1");
220 cookie.setMaxAge(1000);
221 cookies.add(cookie);
222 cookie = new HttpCookie("key2", "value2");
223 cookie.setSecure(true);
224 cookie.setPath("/some/path2");
225 cookie.setDomain("some-domain2");
226 cookie.setMaxAge(1000);
227 cookie.setHttpOnly(true);
228 cookies.add(cookie);
229
230 try (Writer writer = Files.newBufferedWriter(tmpFile,
231 StandardCharsets.US_ASCII)) {
232 NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
233 }
234 Set<HttpCookie> actualCookies = new NetscapeCookieFile(tmpFile,
235 TEST_DATE)
236 .getCookies(true);
237 assertThat(actualCookies, HttpCookiesMatcher.containsInOrder(cookies));
238 }
239
240 @Test
241 public void testReadAndWriteCycle() throws IOException {
242 try (InputStream input = this.getClass()
243 .getResourceAsStream("cookies-simple1.txt")) {
244 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
245 }
246 Set<HttpCookie> cookies = new NetscapeCookieFile(tmpFile, TEST_DATE)
247 .getCookies(true);
248 Path tmpFile2 = folder.newFile().toPath();
249 try (Writer writer = Files.newBufferedWriter(tmpFile2,
250 StandardCharsets.US_ASCII)) {
251 NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
252 }
253
254 assertEquals(Files.readAllLines(tmpFile), Files.readAllLines(tmpFile2));
255 }
256
257 @Test
258 public void testReadWithEmptyAndCommentLines() throws IOException {
259 try (InputStream input = this.getClass().getResourceAsStream(
260 "cookies-with-empty-and-comment-lines.txt")) {
261 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
262 }
263
264 Set<HttpCookie> cookies = new LinkedHashSet<>();
265
266 HttpCookie cookie = new HttpCookie("key2", "value2");
267 cookie.setDomain("some-domain2");
268 cookie.setPath("/some/path2");
269 cookie.setMaxAge(
270 Duration.between(TEST_DATE, TEST_EXPIRY_DATE).getSeconds());
271 cookie.setSecure(true);
272 cookie.setHttpOnly(true);
273 cookies.add(cookie);
274
275 cookie = new HttpCookie("key3", "value3");
276 cookie.setDomain("some-domain3");
277 cookie.setPath("/some/path3");
278 cookie.setMaxAge(
279 Duration.between(TEST_DATE, TEST_EXPIRY_DATE).getSeconds());
280 cookies.add(cookie);
281
282 Set<HttpCookie> actualCookies = new NetscapeCookieFile(tmpFile,
283 TEST_DATE).getCookies(true);
284 assertThat(actualCookies, HttpCookiesMatcher.containsInOrder(cookies));
285 }
286
287 @Test
288 public void testReadInvalidFile() throws IOException {
289 try (InputStream input = this.getClass()
290 .getResourceAsStream("cookies-invalid.txt")) {
291 Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
292 }
293
294 assertTrue(new NetscapeCookieFile(tmpFile, TEST_DATE).getCookies(true)
295 .isEmpty());
296 }
297 }