Skip to content

Commit

Permalink
Preliminary build support for macOS on aarch64 (M1) (#4119)
Browse files Browse the repository at this point in the history
Motivation:

Our current and future contributors can't build Armeria with their M1 MacBooks.

Modifications:

- Fixed the test cases that make false assumption that Brotli codec will
  be always available.
- Fixed `FileService` so that it works as expected even when Brotli
  codec is not available.
- Updated NPM to 8.5.2 for `docs-client`
- Updated `docs-client/package-lock.json`
- Fixed eslint and TypeScript compilation errors
  - Disabled soon-to-be-deprecated eslint rule.
- Fixed a Kotlin compiler warning in `DataClassDocServiceTest`
- Added `-Xskip-prerelease-check` option to Kotlin compiler to work
  around its complaints about the code compiled with a pre-release compiler.
- Misc:
  - Increased the timeout for some assertions, clients and services for
    less flakiness.

Result:

- A contributor can build Armeria on macOS with Apple Silicon (M1).
  - Known issues:
    - `:site` cannot be built yet. Need to upgrade a lot of
      dependencies to make it happen.
    - Parallel build sometimes results in a build failure related with
      duplicate classes in a JAR.
- (defect) `FileService` doesn't choose a `.br` file for generating
  decompressed content anymore when Brotli is not available.
  • Loading branch information
trustin authored Feb 28, 2022
1 parent 5a3057a commit 84cbaf1
Show file tree
Hide file tree
Showing 19 changed files with 8,595 additions and 9,672 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import java.io.File;
import java.nio.file.Path;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Objects;
Expand All @@ -38,6 +37,7 @@
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalListener;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;

import com.linecorp.armeria.common.HttpData;
import com.linecorp.armeria.common.HttpHeaderNames;
Expand All @@ -62,6 +62,7 @@

import io.micrometer.core.instrument.MeterRegistry;
import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.codec.compression.Brotli;

/**
* An {@link HttpService} that serves static files from a file system.
Expand Down Expand Up @@ -215,7 +216,7 @@ private HttpFile findFile(ServiceRequestContext ctx, HttpRequest req) {
}
if (config().autoDecompress() && encodings.isEmpty()) {
needsDecompression = true;
Collections.addAll(encodings, ContentEncoding.values());
encodings.addAll(ContentEncoding.availableEncodings);
}
}
final boolean decompress = needsDecompression;
Expand Down Expand Up @@ -521,6 +522,16 @@ enum ContentEncoding {
BROTLI(".br", "br", StreamDecoderFactory.brotli()),
GZIP(".gz", "gzip", StreamDecoderFactory.gzip());

static final Set<ContentEncoding> availableEncodings;

static {
if (Brotli.isAvailable()) {
availableEncodings = Sets.immutableEnumSet(BROTLI, GZIP);
} else {
availableEncodings = Sets.immutableEnumSet(GZIP);
}
}

private final String extension;
final String headerValue;
final StreamDecoderFactory decoderFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
import com.linecorp.armeria.testing.junit5.server.ServerExtension;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.compression.Brotli;
import io.netty.util.AsciiString;

class HttpClientIntegrationTest {
Expand Down Expand Up @@ -504,7 +505,8 @@ void httpDecoding() throws Exception {

final AggregatedHttpResponse response =
client.execute(RequestHeaders.of(HttpMethod.GET, "/encoding"));
assertThat(response.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo("br");
assertThat(response.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo(
Brotli.isAvailable() ? "br" : "gzip");
assertThat(response.contentUtf8()).isEqualTo(
"some content to compress more content to compress");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.function.Function;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.linecorp.armeria.client.HttpClient;
Expand Down Expand Up @@ -104,6 +105,7 @@ void httpDeflateDecodingTest() throws Exception {
}

@Test
@EnabledIf("io.netty.handler.codec.compression.Brotli#isAvailable")
void httpBrotliDecodingTest() throws Exception {
final WebClient client = WebClient.builder(server.httpUri())
.decorator(DecodingClient.newDecorator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
import static org.assertj.core.api.Assertions.assertThat;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.zip.GZIPInputStream;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand Down Expand Up @@ -55,6 +57,7 @@
import com.linecorp.armeria.testing.junit5.server.ServerExtension;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.compression.Brotli;

class ContentPreviewingClientTest {

Expand Down Expand Up @@ -98,7 +101,8 @@ void decodedContentPreview() {
try (ClientRequestContextCaptor captor = Clients.newContextCaptor()) {
final AggregatedHttpResponse res = client.execute(headers, "Armeria");
assertThat(res.contentUtf8()).isEqualTo("Hello Armeria!");
assertThat(res.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo("br");
assertThat(res.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo(
Brotli.isAvailable() ? "br" : "gzip");
context = captor.get();
}

Expand Down Expand Up @@ -126,7 +130,8 @@ void contentPreviewIsDecodedInPreviewer() {
try (ClientRequestContextCaptor captor = Clients.newContextCaptor()) {
final AggregatedHttpResponse res = client.execute(headers, "Armeria");
assertThat(res.contentUtf8()).isEqualTo("Hello Armeria!");
assertThat(res.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo("br");
assertThat(res.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo(
Brotli.isAvailable() ? "br" : "gzip");
context = captor.get();
}

Expand Down Expand Up @@ -209,12 +214,18 @@ void sanitizeContentPreview() {

private static Function<? super HttpClient, ContentPreviewingClient> decodingContentPreviewDecorator() {
final BiPredicate<? super RequestContext, ? super HttpHeaders> previewerPredicate =
(requestContext, headers) -> "br".equals(headers.get(HttpHeaderNames.CONTENT_ENCODING));
(requestContext, headers) -> {
final String contentEncoding = headers.get(HttpHeaderNames.CONTENT_ENCODING);
return "br".equals(contentEncoding) || "gzip".equals(contentEncoding);
};
final BiFunction<HttpHeaders, ByteBuf, String> producer = (headers, data) -> {
final String contentEncoding = headers.get(HttpHeaderNames.CONTENT_ENCODING);
final byte[] bytes = new byte[data.readableBytes()];
data.getBytes(0, bytes);
final byte[] decoded;
try (BrotliInputStream unzipper = new BrotliInputStream(new ByteArrayInputStream(bytes))) {
final InputStream in = new ByteArrayInputStream(bytes);
try (InputStream unzipper = "br".equals(contentEncoding) ? new BrotliInputStream(in)
: new GZIPInputStream(in)) {
decoded = ByteStreams.toByteArray(unzipper);
} catch (Exception e) {
throw new IllegalArgumentException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@
import java.io.IOException;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;

import com.linecorp.armeria.common.HttpData;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.codec.compression.BrotliDecoder;

@EnabledIf("io.netty.handler.codec.compression.Brotli#isAvailable")
class BrotliStreamDecoderTest {
private static final byte[] PAYLOAD = { -117, 1, -128, 77, 101, 111, 119, 3};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -617,6 +618,7 @@ void testStrings_noAcceptEncoding(WebClient client) throws Exception {

@ParameterizedTest
@ArgumentsSource(ClientAndProtocolProvider.class)
@EnabledIf("io.netty.handler.codec.compression.Brotli#isAvailable")
void testStrings_acceptEncodingBrotli(WebClient client) throws Exception {
final RequestHeaders req = RequestHeaders.of(HttpMethod.GET, "/strings",
HttpHeaderNames.ACCEPT_ENCODING, "br");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.zip.GZIPOutputStream;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.aayushatharva.brotli4j.encoder.BrotliOutputStream;
Expand Down Expand Up @@ -103,6 +104,7 @@ void decodingDeflatedPayloadFromClient() throws IOException {
}

@Test
@EnabledIf("io.netty.handler.codec.compression.Brotli#isAvailable")
void decodingBrotliCompressedPayloadFromClient() throws Throwable {

final WebClient client = WebClient.builder(server.httpUri()).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.RequestHeaders;

import io.netty.handler.codec.compression.Brotli;

public class HttpEncodersTest {
@Rule public MockitoRule mocks = MockitoJUnit.rule();

Expand Down Expand Up @@ -59,7 +61,8 @@ public void acceptEncodingDeflate() {
public void acceptEncodingBrotli() {
when(request.headers()).thenReturn(RequestHeaders.of(HttpMethod.GET, "/",
HttpHeaderNames.ACCEPT_ENCODING, "br"));
assertThat(HttpEncoders.getWrapperForRequest(request)).isEqualTo(HttpEncodingType.BROTLI);
assertThat(HttpEncoders.getWrapperForRequest(request)).isEqualTo(
Brotli.isAvailable() ? HttpEncodingType.BROTLI : null);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
import static org.mockito.Mockito.when;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.zip.GZIPInputStream;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -72,6 +74,7 @@
import com.linecorp.armeria.testing.junit5.server.ServerExtension;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.compression.Brotli;

class ContentPreviewingServiceTest {

Expand Down Expand Up @@ -147,13 +150,19 @@ protected void configure(ServerBuilder sb) throws Exception {

private Function<? super HttpService, ContentPreviewingService> decodingContentPreviewDecorator() {
final BiPredicate<? super RequestContext, ? super HttpHeaders> previewerPredicate =
(requestContext, headers) -> "br".equals(headers.get(HttpHeaderNames.CONTENT_ENCODING));
(requestContext, headers) -> {
final String contentEncoding = headers.get(HttpHeaderNames.CONTENT_ENCODING);
return "br".equals(contentEncoding) || "gzip".equals(contentEncoding);
};

final BiFunction<HttpHeaders, ByteBuf, String> producer = (headers, data) -> {
final String contentEncoding = headers.get(HttpHeaderNames.CONTENT_ENCODING);
final byte[] bytes = new byte[data.readableBytes()];
data.getBytes(0, bytes);
final byte[] decoded;
try (BrotliInputStream unzipper = new BrotliInputStream(new ByteArrayInputStream(bytes))) {
final InputStream in = new ByteArrayInputStream(bytes);
try (InputStream unzipper = "br".equals(contentEncoding) ? new BrotliInputStream(in)
: new GZIPInputStream(in)) {
decoded = ByteStreams.toByteArray(unzipper);
} catch (Exception e) {
throw new IllegalArgumentException(e);
Expand Down Expand Up @@ -202,7 +211,8 @@ void encodedContentPreviewIsDecodedInPreviewer() {
HttpHeaderNames.CONTENT_TYPE, "text/plain");
final AggregatedHttpResponse res = client.execute(headers, "Armeria").aggregate().join();
assertThat(res.contentUtf8()).isEqualTo("Hello Armeria!");
assertThat(res.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo("br");
assertThat(res.headers().get(HttpHeaderNames.CONTENT_ENCODING)).isEqualTo(
Brotli.isAvailable() ? "br" : "gzip");

final RequestLog requestLog = contextCaptor.get().log().whenComplete().join();
assertThat(requestLog.requestContentPreview()).isEqualTo("Armeria");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.assertj.core.api.Assertions.assertThat;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;

Expand Down Expand Up @@ -52,6 +53,7 @@ class ManagementServiceTest {
static ServerExtension server = new ServerExtension() {
@Override
protected void configure(ServerBuilder sb) {
sb.requestTimeout(Duration.ofSeconds(45)); // Heap dump can take time.
sb.serviceUnder("/internal/management", ManagementService.of());
}
};
Expand Down Expand Up @@ -84,7 +86,9 @@ void threadDumpWithJson() throws Exception {

@Test
void heapDump() throws InterruptedException {
final WebClient client = WebClient.of(server.httpUri());
final WebClient client = WebClient.builder(server.httpUri())
.responseTimeout(Duration.ofSeconds(50)) // Heap dump can take time.
.build();
final HttpResponse response = client.get("/internal/management/jvm/heapdump");
final SplitHttpResponse splitHttpResponse = response.split();
final ResponseHeaders headers = splitHttpResponse.headers().join();
Expand Down
2 changes: 1 addition & 1 deletion docs-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ apply plugin: 'com.github.node-gradle.node'

node {
version = '16.14.0'
npmVersion = '6.14.16'
npmVersion = '8.5.2'
download = true
npmInstallCommand = "ci"

Expand Down
Loading

0 comments on commit 84cbaf1

Please sign in to comment.