You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NetscapeCookieFileTest.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Copyright (C) 2018, Konrad Windszus <konrad_w@gmx.de> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.internal.transport.http;
  11. import static org.hamcrest.MatcherAssert.assertThat;
  12. import static org.junit.Assert.assertEquals;
  13. import static org.junit.Assert.assertTrue;
  14. import java.io.IOException;
  15. import java.io.InputStream;
  16. import java.io.Writer;
  17. import java.net.HttpCookie;
  18. import java.net.URL;
  19. import java.nio.charset.StandardCharsets;
  20. import java.nio.file.Files;
  21. import java.nio.file.Path;
  22. import java.nio.file.StandardCopyOption;
  23. import java.time.Duration;
  24. import java.time.Instant;
  25. import java.time.temporal.ChronoUnit;
  26. import java.util.Arrays;
  27. import java.util.LinkedHashSet;
  28. import java.util.List;
  29. import java.util.Set;
  30. import org.eclipse.jgit.internal.storage.file.LockFile;
  31. import org.eclipse.jgit.util.http.HttpCookiesMatcher;
  32. import org.hamcrest.CoreMatchers;
  33. import org.junit.Before;
  34. import org.junit.Rule;
  35. import org.junit.Test;
  36. import org.junit.rules.TemporaryFolder;
  37. public class NetscapeCookieFileTest {
  38. @Rule
  39. public TemporaryFolder folder = new TemporaryFolder();
  40. private Path tmpFile;
  41. private URL baseUrl;
  42. /**
  43. * This is the expiration date that is used in the test cookie files.
  44. */
  45. private static final Instant TEST_EXPIRY_DATE = Instant
  46. .parse("2030-01-01T12:00:00.000Z");
  47. /** Earlier than TEST_EXPIRY_DATE. */
  48. private static final Instant TEST_DATE = TEST_EXPIRY_DATE.minus(180,
  49. ChronoUnit.DAYS);
  50. @Before
  51. public void setUp() throws IOException {
  52. // this will not only return a new file name but also create new empty
  53. // file!
  54. tmpFile = folder.newFile().toPath();
  55. baseUrl = new URL("http://domain.com/my/path");
  56. }
  57. @Test
  58. public void testMergeCookies() {
  59. Set<HttpCookie> cookieSet1 = new LinkedHashSet<>();
  60. HttpCookie cookie = new HttpCookie("key1", "valueFromSet1");
  61. cookieSet1.add(cookie);
  62. cookie = new HttpCookie("key2", "valueFromSet1");
  63. cookieSet1.add(cookie);
  64. Set<HttpCookie> cookieSet2 = new LinkedHashSet<>();
  65. cookie = new HttpCookie("key1", "valueFromSet2");
  66. cookieSet2.add(cookie);
  67. cookie = new HttpCookie("key3", "valueFromSet2");
  68. cookieSet2.add(cookie);
  69. Set<HttpCookie> cookiesExpectedMergedSet = new LinkedHashSet<>();
  70. cookie = new HttpCookie("key1", "valueFromSet1");
  71. cookiesExpectedMergedSet.add(cookie);
  72. cookie = new HttpCookie("key2", "valueFromSet1");
  73. cookiesExpectedMergedSet.add(cookie);
  74. cookie = new HttpCookie("key3", "valueFromSet2");
  75. cookiesExpectedMergedSet.add(cookie);
  76. assertThat(NetscapeCookieFile.mergeCookies(cookieSet1, cookieSet2),
  77. HttpCookiesMatcher.containsInOrder(cookiesExpectedMergedSet));
  78. assertThat(NetscapeCookieFile.mergeCookies(cookieSet1, null),
  79. HttpCookiesMatcher.containsInOrder(cookieSet1));
  80. }
  81. @Test
  82. public void testWriteToNewFile() throws IOException {
  83. Set<HttpCookie> cookies = new LinkedHashSet<>();
  84. cookies.add(new HttpCookie("key1", "value"));
  85. // first cookie is a session cookie (and should be ignored)
  86. HttpCookie cookie = new HttpCookie("key2", "value");
  87. cookie.setSecure(true);
  88. cookie.setDomain("mydomain.com");
  89. cookie.setPath("/");
  90. cookie.setMaxAge(1000);
  91. cookies.add(cookie);
  92. try (Writer writer = Files.newBufferedWriter(tmpFile,
  93. StandardCharsets.US_ASCII)) {
  94. NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
  95. }
  96. String expectedExpiration = String
  97. .valueOf(TEST_DATE.getEpochSecond() + cookie.getMaxAge());
  98. assertThat(Files.readAllLines(tmpFile, StandardCharsets.US_ASCII),
  99. CoreMatchers
  100. .equalTo(Arrays.asList("mydomain.com\tTRUE\t/\tTRUE\t"
  101. + expectedExpiration + "\tkey2\tvalue")));
  102. }
  103. @Test
  104. public void testWriteToExistingFile() throws IOException {
  105. try (InputStream input = this.getClass()
  106. .getResourceAsStream("cookies-simple1.txt")) {
  107. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  108. }
  109. Set<HttpCookie> cookies = new LinkedHashSet<>();
  110. HttpCookie cookie = new HttpCookie("key2", "value2");
  111. cookie.setMaxAge(1000);
  112. cookies.add(cookie);
  113. try (Writer writer = Files.newBufferedWriter(tmpFile,
  114. StandardCharsets.US_ASCII)) {
  115. NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
  116. }
  117. String expectedExpiration = String
  118. .valueOf(TEST_DATE.getEpochSecond() + cookie.getMaxAge());
  119. assertThat(Files.readAllLines(tmpFile, StandardCharsets.US_ASCII),
  120. CoreMatchers.equalTo(
  121. Arrays.asList("domain.com\tTRUE\t/my/path\tFALSE\t"
  122. + expectedExpiration + "\tkey2\tvalue2")));
  123. }
  124. @Test(expected = IOException.class)
  125. public void testWriteWhileSomeoneIsHoldingTheLock()
  126. throws IllegalArgumentException, IOException, InterruptedException {
  127. try (InputStream input = this.getClass()
  128. .getResourceAsStream("cookies-simple1.txt")) {
  129. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  130. }
  131. NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile);
  132. // now imitate another process/thread holding the lock file
  133. LockFile lockFile = new LockFile(tmpFile.toFile());
  134. try {
  135. assertTrue("Could not acquire lock", lockFile.lock());
  136. cookieFile.write(baseUrl);
  137. } finally {
  138. lockFile.unlock();
  139. }
  140. }
  141. @Test
  142. public void testReadCookieFileWithMilliseconds() throws IOException {
  143. try (InputStream input = this.getClass()
  144. .getResourceAsStream("cookies-with-milliseconds.txt")) {
  145. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  146. }
  147. NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile,
  148. TEST_DATE);
  149. long expectedMaxAge = Duration.between(TEST_DATE, TEST_EXPIRY_DATE)
  150. .getSeconds();
  151. for (HttpCookie cookie : cookieFile.getCookies(true)) {
  152. assertEquals(expectedMaxAge, cookie.getMaxAge());
  153. }
  154. }
  155. @Test
  156. public void testWriteAfterAnotherJgitProcessModifiedTheFile()
  157. throws IOException, InterruptedException {
  158. try (InputStream input = this.getClass()
  159. .getResourceAsStream("cookies-simple1.txt")) {
  160. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  161. }
  162. NetscapeCookieFile cookieFile = new NetscapeCookieFile(tmpFile,
  163. TEST_DATE);
  164. cookieFile.getCookies(true);
  165. // now modify file externally
  166. try (InputStream input = this.getClass()
  167. .getResourceAsStream("cookies-simple2.txt")) {
  168. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  169. }
  170. // now try to write
  171. cookieFile.write(baseUrl);
  172. List<String> lines = Files.readAllLines(tmpFile,
  173. StandardCharsets.US_ASCII);
  174. assertEquals("Expected 3 lines", 3, lines.size());
  175. assertEquals(
  176. "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey1\tvalueFromSimple2",
  177. lines.get(0));
  178. assertEquals(
  179. "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey3\tvalueFromSimple2",
  180. lines.get(1));
  181. assertEquals(
  182. "some-domain1\tTRUE\t/some/path1\tFALSE\t1893499200\tkey2\tvalueFromSimple1",
  183. lines.get(2));
  184. }
  185. @Test
  186. public void testWriteAndReadCycle() throws IOException {
  187. Set<HttpCookie> cookies = new LinkedHashSet<>();
  188. HttpCookie cookie = new HttpCookie("key1", "value1");
  189. cookie.setPath("/some/path1");
  190. cookie.setDomain("some-domain1");
  191. cookie.setMaxAge(1000);
  192. cookies.add(cookie);
  193. cookie = new HttpCookie("key2", "value2");
  194. cookie.setSecure(true);
  195. cookie.setPath("/some/path2");
  196. cookie.setDomain("some-domain2");
  197. cookie.setMaxAge(1000);
  198. cookie.setHttpOnly(true);
  199. cookies.add(cookie);
  200. try (Writer writer = Files.newBufferedWriter(tmpFile,
  201. StandardCharsets.US_ASCII)) {
  202. NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
  203. }
  204. Set<HttpCookie> actualCookies = new NetscapeCookieFile(tmpFile,
  205. TEST_DATE)
  206. .getCookies(true);
  207. assertThat(actualCookies, HttpCookiesMatcher.containsInOrder(cookies));
  208. }
  209. @Test
  210. public void testReadAndWriteCycle() throws IOException {
  211. try (InputStream input = this.getClass()
  212. .getResourceAsStream("cookies-simple1.txt")) {
  213. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  214. }
  215. Set<HttpCookie> cookies = new NetscapeCookieFile(tmpFile, TEST_DATE)
  216. .getCookies(true);
  217. Path tmpFile2 = folder.newFile().toPath();
  218. try (Writer writer = Files.newBufferedWriter(tmpFile2,
  219. StandardCharsets.US_ASCII)) {
  220. NetscapeCookieFile.write(writer, cookies, baseUrl, TEST_DATE);
  221. }
  222. // compare original file with newly written one, they should not differ
  223. assertEquals(Files.readAllLines(tmpFile), Files.readAllLines(tmpFile2));
  224. }
  225. @Test
  226. public void testReadWithEmptyAndCommentLines() throws IOException {
  227. try (InputStream input = this.getClass().getResourceAsStream(
  228. "cookies-with-empty-and-comment-lines.txt")) {
  229. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  230. }
  231. Set<HttpCookie> cookies = new LinkedHashSet<>();
  232. HttpCookie cookie = new HttpCookie("key2", "value2");
  233. cookie.setDomain("some-domain2");
  234. cookie.setPath("/some/path2");
  235. cookie.setMaxAge(
  236. Duration.between(TEST_DATE, TEST_EXPIRY_DATE).getSeconds());
  237. cookie.setSecure(true);
  238. cookie.setHttpOnly(true);
  239. cookies.add(cookie);
  240. cookie = new HttpCookie("key3", "value3");
  241. cookie.setDomain("some-domain3");
  242. cookie.setPath("/some/path3");
  243. cookie.setMaxAge(
  244. Duration.between(TEST_DATE, TEST_EXPIRY_DATE).getSeconds());
  245. cookies.add(cookie);
  246. Set<HttpCookie> actualCookies = new NetscapeCookieFile(tmpFile,
  247. TEST_DATE).getCookies(true);
  248. assertThat(actualCookies, HttpCookiesMatcher.containsInOrder(cookies));
  249. }
  250. @Test
  251. public void testReadInvalidFile() throws IOException {
  252. try (InputStream input = this.getClass()
  253. .getResourceAsStream("cookies-invalid.txt")) {
  254. Files.copy(input, tmpFile, StandardCopyOption.REPLACE_EXISTING);
  255. }
  256. assertTrue(new NetscapeCookieFile(tmpFile, TEST_DATE).getCookies(true)
  257. .isEmpty());
  258. }
  259. }