Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-11.0.x
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
commit
aeeed200dc
|
@ -3,11 +3,13 @@ aif=audio/x-aiff
|
|||
aifc=audio/x-aiff
|
||||
aiff=audio/x-aiff
|
||||
apk=application/vnd.android.package-archive
|
||||
apng=image/apng
|
||||
asc=text/plain
|
||||
asf=video/x.ms.asf
|
||||
asx=video/x.ms.asx
|
||||
au=audio/basic
|
||||
avi=video/x-msvideo
|
||||
avif=image/avif
|
||||
bcpio=application/x-bcpio
|
||||
bin=application/octet-stream
|
||||
bmp=image/bmp
|
||||
|
@ -170,6 +172,7 @@ vxml=application/voicexml+xml
|
|||
wasm=application/wasm
|
||||
wav=audio/x-wav
|
||||
wbmp=image/vnd.wap.wbmp
|
||||
webp=image/webp
|
||||
wml=text/vnd.wap.wml
|
||||
wmlc=application/vnd.wap.wmlc
|
||||
wmls=text/vnd.wap.wmlscript
|
||||
|
|
|
@ -13,47 +13,48 @@
|
|||
|
||||
package org.eclipse.jetty.http;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
public class MimeTypesTest
|
||||
{
|
||||
@Test
|
||||
public void testGetMimeByExtensionGzip()
|
||||
public static Stream<Arguments> mimeTypesByExtensionCases()
|
||||
{
|
||||
assertMimeTypeByExtension("application/gzip", "test.gz");
|
||||
return Stream.of(
|
||||
Arguments.of("test.gz", "application/gzip"),
|
||||
Arguments.of("foo.webp", "image/webp"),
|
||||
Arguments.of("zed.avif", "image/avif"),
|
||||
// make sure that filename case isn't an issue
|
||||
Arguments.of("test.png", "image/png"),
|
||||
Arguments.of("TEST.PNG", "image/png"),
|
||||
Arguments.of("Test.Png", "image/png"),
|
||||
Arguments.of("test.txt", "text/plain"),
|
||||
Arguments.of("TEST.TXT", "text/plain"),
|
||||
// Make sure that multiple dots don't interfere
|
||||
Arguments.of("org.eclipse.jetty.Logo.png", "image/png"),
|
||||
// Make sure that a deep path doesn't interfere
|
||||
Arguments.of("org/eclipse/jetty/Logo.png", "image/png"),
|
||||
// Make sure that path that looks like a filename doesn't interfere
|
||||
Arguments.of("org/eclipse.jpg/jetty/Logo.png", "image/png")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMimeByExtensionPng()
|
||||
@ParameterizedTest
|
||||
@MethodSource("mimeTypesByExtensionCases")
|
||||
public void testMimeTypesByExtension(String filename, String expectedMimeType)
|
||||
{
|
||||
assertMimeTypeByExtension("image/png", "test.png");
|
||||
assertMimeTypeByExtension("image/png", "TEST.PNG");
|
||||
assertMimeTypeByExtension("image/png", "Test.Png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMimeByExtensionPngMultiDot()
|
||||
{
|
||||
assertMimeTypeByExtension("image/png", "org.eclipse.jetty.Logo.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMimeByExtensionPngDeepPath()
|
||||
{
|
||||
assertMimeTypeByExtension("image/png", "/org/eclipse/jetty/Logo.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMimeByExtensionText()
|
||||
{
|
||||
assertMimeTypeByExtension("text/plain", "test.txt");
|
||||
assertMimeTypeByExtension("text/plain", "TEST.TXT");
|
||||
MimeTypes mimetypes = new MimeTypes();
|
||||
String contentType = mimetypes.getMimeByExtension(filename);
|
||||
assertThat("MimeTypes.getMimeByExtension(\"" + filename + "\")",
|
||||
contentType, is(expectedMimeType));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -64,60 +65,63 @@ public class MimeTypesTest
|
|||
assertNull(contentType);
|
||||
}
|
||||
|
||||
private void assertMimeTypeByExtension(String expectedMimeType, String filename)
|
||||
public static Stream<Arguments> charsetFromContentTypeCases()
|
||||
{
|
||||
MimeTypes mimetypes = new MimeTypes();
|
||||
String contentType = mimetypes.getMimeByExtension(filename);
|
||||
String prefix = "MimeTypes.getMimeByExtension(" + filename + ")";
|
||||
assertNotNull(contentType, prefix);
|
||||
assertEquals(expectedMimeType, contentType, prefix);
|
||||
return Stream.of(
|
||||
Arguments.of("foo/bar;charset=abc;some=else", "abc"),
|
||||
Arguments.of("foo/bar;charset=abc", "abc"),
|
||||
Arguments.of("foo/bar ; charset = abc", "abc"),
|
||||
Arguments.of("foo/bar ; charset = abc ; some=else", "abc"),
|
||||
Arguments.of("foo/bar;other=param;charset=abc;some=else", "abc"),
|
||||
Arguments.of("foo/bar;other=param;charset=abc", "abc"),
|
||||
Arguments.of("foo/bar other = param ; charset = abc", "abc"),
|
||||
Arguments.of("foo/bar other = param ; charset = abc ; some=else", "abc"),
|
||||
Arguments.of("foo/bar other = param ; charset = abc", "abc"),
|
||||
Arguments.of("foo/bar other = param ; charset = \"abc\" ; some=else", "abc"),
|
||||
Arguments.of("foo/bar", null),
|
||||
Arguments.of("foo/bar;charset=uTf8", "utf-8"),
|
||||
Arguments.of("foo/bar;other=\"charset=abc\";charset=uTf8", "utf-8"),
|
||||
Arguments.of("application/pdf; charset=UTF-8", "utf-8"),
|
||||
Arguments.of("application/pdf;; charset=UTF-8", "utf-8"),
|
||||
Arguments.of("application/pdf;;; charset=UTF-8", "utf-8"),
|
||||
Arguments.of("application/pdf;;;; charset=UTF-8", "utf-8"),
|
||||
Arguments.of("text/html;charset=utf-8", "utf-8")
|
||||
);
|
||||
}
|
||||
|
||||
private void assertCharsetFromContentType(String contentType, String expectedCharset)
|
||||
@ParameterizedTest
|
||||
@MethodSource("charsetFromContentTypeCases")
|
||||
public void testCharsetFromContentType(String contentType, String expectedCharset)
|
||||
{
|
||||
assertThat("getCharsetFromContentType(\"" + contentType + "\")",
|
||||
MimeTypes.getCharsetFromContentType(contentType), is(expectedCharset));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCharsetFromContentType()
|
||||
public static Stream<Arguments> contentTypeWithoutCharsetCases()
|
||||
{
|
||||
assertCharsetFromContentType("foo/bar;charset=abc;some=else", "abc");
|
||||
assertCharsetFromContentType("foo/bar;charset=abc", "abc");
|
||||
assertCharsetFromContentType("foo/bar ; charset = abc", "abc");
|
||||
assertCharsetFromContentType("foo/bar ; charset = abc ; some=else", "abc");
|
||||
assertCharsetFromContentType("foo/bar;other=param;charset=abc;some=else", "abc");
|
||||
assertCharsetFromContentType("foo/bar;other=param;charset=abc", "abc");
|
||||
assertCharsetFromContentType("foo/bar other = param ; charset = abc", "abc");
|
||||
assertCharsetFromContentType("foo/bar other = param ; charset = abc ; some=else", "abc");
|
||||
assertCharsetFromContentType("foo/bar other = param ; charset = abc", "abc");
|
||||
assertCharsetFromContentType("foo/bar other = param ; charset = \"abc\" ; some=else", "abc");
|
||||
assertCharsetFromContentType("foo/bar", null);
|
||||
assertCharsetFromContentType("foo/bar;charset=uTf8", "utf-8");
|
||||
assertCharsetFromContentType("foo/bar;other=\"charset=abc\";charset=uTf8", "utf-8");
|
||||
assertCharsetFromContentType("application/pdf; charset=UTF-8", "utf-8");
|
||||
assertCharsetFromContentType("application/pdf;; charset=UTF-8", "utf-8");
|
||||
assertCharsetFromContentType("application/pdf;;; charset=UTF-8", "utf-8");
|
||||
assertCharsetFromContentType("application/pdf;;;; charset=UTF-8", "utf-8");
|
||||
assertCharsetFromContentType("text/html;charset=utf-8", "utf-8");
|
||||
return Stream.of(
|
||||
Arguments.of("foo/bar;charset=abc;some=else", "foo/bar;some=else"),
|
||||
Arguments.of("foo/bar;charset=abc", "foo/bar"),
|
||||
Arguments.of("foo/bar ; charset = abc", "foo/bar"),
|
||||
Arguments.of("foo/bar ; charset = abc ; some=else", "foo/bar;some=else"),
|
||||
Arguments.of("foo/bar;other=param;charset=abc;some=else", "foo/bar;other=param;some=else"),
|
||||
Arguments.of("foo/bar;other=param;charset=abc", "foo/bar;other=param"),
|
||||
Arguments.of("foo/bar ; other = param ; charset = abc", "foo/bar ; other = param"),
|
||||
Arguments.of("foo/bar ; other = param ; charset = abc ; some=else", "foo/bar ; other = param;some=else"),
|
||||
Arguments.of("foo/bar ; other = param ; charset = abc", "foo/bar ; other = param"),
|
||||
Arguments.of("foo/bar ; other = param ; charset = \"abc\" ; some=else", "foo/bar ; other = param;some=else"),
|
||||
Arguments.of("foo/bar", "foo/bar"),
|
||||
Arguments.of("foo/bar;charset=uTf8", "foo/bar"),
|
||||
Arguments.of("foo/bar;other=\"charset=abc\";charset=uTf8", "foo/bar;other=\"charset=abc\""),
|
||||
Arguments.of("text/html;charset=utf-8", "text/html")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContentTypeWithoutCharset()
|
||||
@ParameterizedTest
|
||||
@MethodSource("contentTypeWithoutCharsetCases")
|
||||
public void testContentTypeWithoutCharset(String contentTypeWithCharset, String expectedContentType)
|
||||
{
|
||||
assertEquals("foo/bar;some=else", MimeTypes.getContentTypeWithoutCharset("foo/bar;charset=abc;some=else"));
|
||||
assertEquals("foo/bar", MimeTypes.getContentTypeWithoutCharset("foo/bar;charset=abc"));
|
||||
assertEquals("foo/bar", MimeTypes.getContentTypeWithoutCharset("foo/bar ; charset = abc"));
|
||||
assertEquals("foo/bar;some=else", MimeTypes.getContentTypeWithoutCharset("foo/bar ; charset = abc ; some=else"));
|
||||
assertEquals("foo/bar;other=param;some=else", MimeTypes.getContentTypeWithoutCharset("foo/bar;other=param;charset=abc;some=else"));
|
||||
assertEquals("foo/bar;other=param", MimeTypes.getContentTypeWithoutCharset("foo/bar;other=param;charset=abc"));
|
||||
assertEquals("foo/bar ; other = param", MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = abc"));
|
||||
assertEquals("foo/bar ; other = param;some=else", MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = abc ; some=else"));
|
||||
assertEquals("foo/bar ; other = param", MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = abc"));
|
||||
assertEquals("foo/bar ; other = param;some=else", MimeTypes.getContentTypeWithoutCharset("foo/bar ; other = param ; charset = \"abc\" ; some=else"));
|
||||
assertEquals("foo/bar", MimeTypes.getContentTypeWithoutCharset("foo/bar"));
|
||||
assertEquals("foo/bar", MimeTypes.getContentTypeWithoutCharset("foo/bar;charset=uTf8"));
|
||||
assertEquals("foo/bar;other=\"charset=abc\"", MimeTypes.getContentTypeWithoutCharset("foo/bar;other=\"charset=abc\";charset=uTf8"));
|
||||
assertEquals("text/html", MimeTypes.getContentTypeWithoutCharset("text/html;charset=utf-8"));
|
||||
assertThat("MimeTypes.getContentTypeWithoutCharset(\"" + contentTypeWithCharset + "\")",
|
||||
MimeTypes.getContentTypeWithoutCharset(contentTypeWithCharset), is(expectedContentType));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,23 +13,28 @@
|
|||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
|
||||
|
||||
import static org.eclipse.jetty.util.BlockingArrayQueueTest.Await.await;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
@ -161,12 +166,12 @@ public class BlockingArrayQueueTest
|
|||
}
|
||||
|
||||
@Test
|
||||
@DisabledIfSystemProperty(named = "env", matches = "ci") // TODO: SLOW, needs review
|
||||
public void testTake() throws Exception
|
||||
{
|
||||
final String[] data = new String[4];
|
||||
|
||||
final BlockingArrayQueue<String> queue = new BlockingArrayQueue<>();
|
||||
CyclicBarrier barrier = new CyclicBarrier(2);
|
||||
|
||||
Thread thread = new Thread()
|
||||
{
|
||||
|
@ -177,7 +182,7 @@ public class BlockingArrayQueueTest
|
|||
{
|
||||
data[0] = queue.take();
|
||||
data[1] = queue.take();
|
||||
Thread.sleep(1000);
|
||||
barrier.await(5, TimeUnit.SECONDS); // Wait until the main thread already called offer().
|
||||
data[2] = queue.take();
|
||||
data[3] = queue.poll(100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
@ -191,35 +196,36 @@ public class BlockingArrayQueueTest
|
|||
|
||||
thread.start();
|
||||
|
||||
Thread.sleep(1000);
|
||||
// Wait until the spawned thread is blocked in queue.take().
|
||||
await().atMost(5, TimeUnit.SECONDS).until(() -> thread.getState() == Thread.State.WAITING);
|
||||
|
||||
queue.offer("zero");
|
||||
queue.offer("one");
|
||||
queue.offer("two");
|
||||
barrier.await(5, TimeUnit.SECONDS); // Notify the spawned thread that offer() was called.
|
||||
thread.join();
|
||||
|
||||
assertEquals("zero", data[0]);
|
||||
assertEquals("one", data[1]);
|
||||
assertEquals("two", data[2]);
|
||||
assertEquals(null, data[3]);
|
||||
assertNull(data[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledIfSystemProperty(named = "env", matches = "ci") // TODO: SLOW, needs review
|
||||
public void testConcurrentAccess() throws Exception
|
||||
{
|
||||
final int THREADS = 50;
|
||||
final int THREADS = 32;
|
||||
final int LOOPS = 1000;
|
||||
|
||||
final BlockingArrayQueue<Integer> queue = new BlockingArrayQueue<>(1 + THREADS * LOOPS);
|
||||
BlockingArrayQueue<Integer> queue = new BlockingArrayQueue<>(1 + THREADS * LOOPS);
|
||||
|
||||
final ConcurrentLinkedQueue<Integer> produced = new ConcurrentLinkedQueue<>();
|
||||
final ConcurrentLinkedQueue<Integer> consumed = new ConcurrentLinkedQueue<>();
|
||||
Set<Integer> produced = ConcurrentHashMap.newKeySet();
|
||||
Set<Integer> consumed = ConcurrentHashMap.newKeySet();
|
||||
|
||||
final AtomicBoolean running = new AtomicBoolean(true);
|
||||
AtomicBoolean consumersRunning = new AtomicBoolean(true);
|
||||
|
||||
// start consumers
|
||||
final CyclicBarrier barrier0 = new CyclicBarrier(THREADS + 1);
|
||||
CyclicBarrier consumersBarrier = new CyclicBarrier(THREADS + 1);
|
||||
for (int i = 0; i < THREADS; i++)
|
||||
{
|
||||
new Thread()
|
||||
|
@ -227,20 +233,18 @@ public class BlockingArrayQueueTest
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
final Random random = new Random();
|
||||
|
||||
setPriority(getPriority() - 1);
|
||||
try
|
||||
{
|
||||
while (running.get())
|
||||
while (consumersRunning.get())
|
||||
{
|
||||
int r = 1 + random.nextInt(10);
|
||||
int r = 1 + ThreadLocalRandom.current().nextInt(10);
|
||||
if (r % 2 == 0)
|
||||
{
|
||||
Integer msg = queue.poll();
|
||||
if (msg == null)
|
||||
{
|
||||
Thread.sleep(1 + random.nextInt(10));
|
||||
Thread.sleep(ThreadLocalRandom.current().nextInt(2));
|
||||
continue;
|
||||
}
|
||||
consumed.add(msg);
|
||||
|
@ -261,7 +265,7 @@ public class BlockingArrayQueueTest
|
|||
{
|
||||
try
|
||||
{
|
||||
barrier0.await();
|
||||
consumersBarrier.await();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -273,7 +277,7 @@ public class BlockingArrayQueueTest
|
|||
}
|
||||
|
||||
// start producers
|
||||
final CyclicBarrier barrier1 = new CyclicBarrier(THREADS + 1);
|
||||
CyclicBarrier producersBarrier = new CyclicBarrier(THREADS + 1);
|
||||
for (int i = 0; i < THREADS; i++)
|
||||
{
|
||||
final int id = i;
|
||||
|
@ -282,16 +286,15 @@ public class BlockingArrayQueueTest
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
final Random random = new Random();
|
||||
try
|
||||
{
|
||||
for (int j = 0; j < LOOPS; j++)
|
||||
{
|
||||
Integer msg = random.nextInt();
|
||||
Integer msg = ThreadLocalRandom.current().nextInt();
|
||||
produced.add(msg);
|
||||
if (!queue.offer(msg))
|
||||
throw new Exception(id + " FULL! " + queue.size());
|
||||
Thread.sleep(1 + random.nextInt(10));
|
||||
Thread.sleep(ThreadLocalRandom.current().nextInt(2));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -302,7 +305,7 @@ public class BlockingArrayQueueTest
|
|||
{
|
||||
try
|
||||
{
|
||||
barrier1.await();
|
||||
producersBarrier.await();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -313,22 +316,22 @@ public class BlockingArrayQueueTest
|
|||
}.start();
|
||||
}
|
||||
|
||||
barrier1.await();
|
||||
int size = queue.size();
|
||||
int last = size - 1;
|
||||
while (size > 0 && size != last)
|
||||
producersBarrier.await();
|
||||
|
||||
AtomicInteger last = new AtomicInteger(queue.size() - 1);
|
||||
await().atMost(5, TimeUnit.SECONDS).until(() ->
|
||||
{
|
||||
last = size;
|
||||
Thread.sleep(500);
|
||||
size = queue.size();
|
||||
}
|
||||
running.set(false);
|
||||
barrier0.await();
|
||||
int size = queue.size();
|
||||
if (size == 0 && last.get() == size)
|
||||
return true;
|
||||
last.set(size);
|
||||
return false;
|
||||
});
|
||||
|
||||
HashSet<Integer> prodSet = new HashSet<>(produced);
|
||||
HashSet<Integer> consSet = new HashSet<>(consumed);
|
||||
consumersRunning.set(false);
|
||||
consumersBarrier.await();
|
||||
|
||||
assertEquals(prodSet, consSet);
|
||||
assertEquals(produced, consumed);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -525,4 +528,35 @@ public class BlockingArrayQueueTest
|
|||
assertThat(queue.size(), Matchers.is(0));
|
||||
assertThat(queue, Matchers.empty());
|
||||
}
|
||||
|
||||
static class Await
|
||||
{
|
||||
private Duration duration;
|
||||
|
||||
public static Await await()
|
||||
{
|
||||
return new Await();
|
||||
}
|
||||
|
||||
public Await atMost(long time, TimeUnit unit)
|
||||
{
|
||||
duration = Duration.ofMillis(unit.toMillis(time));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void until(Callable<Boolean> condition) throws Exception
|
||||
{
|
||||
Objects.requireNonNull(duration);
|
||||
long start = System.nanoTime();
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (condition.call())
|
||||
return;
|
||||
if (duration.minus(Duration.ofNanos(System.nanoTime() - start)).isNegative())
|
||||
throw new AssertionError("Duration expired");
|
||||
Thread.sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue