/* * Copyright 2016 LINE Corporation * * LINE Corporation licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.linecorp.armeria.server; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import org.junit.Test; import com.linecorp.armeria.common.RpcRequest; import com.linecorp.armeria.common.RpcResponse; public class ServiceTest { /** * Tests if a user can write a decorator with working as() and serviceAdded() using lambda expressions only. */ @Test public void lambdaExpressionDecorator() throws Exception { final FooService inner = new FooService(); final Service<RpcRequest, RpcResponse> outer = inner.decorate((delegate, ctx, req) -> { RpcRequest newReq = RpcRequest.of(req.serviceType(), "new_" + req.method(), req.params()); return delegate.serve(ctx, newReq); }); assertDecoration(inner, outer); } /** * Tests {@link Service#decorate(Class)}. */ @Test public void reflectionDecorator() throws Exception { final FooService inner = new FooService(); final FooServiceDecorator outer = inner.decorate(FooServiceDecorator.class); assertDecoration(inner, outer); assertThatThrownBy(() -> inner.decorate(BadFooServiceDecorator.class)) .isInstanceOf(IllegalArgumentException.class); } private static void assertDecoration( FooService inner, Service<RpcRequest, RpcResponse> outer) throws Exception { // Test if Service.as() works as expected. assertThat(outer.as(serviceType(inner))).containsSame(inner); assertThat(outer.as(serviceType(outer))).containsSame(outer); assertThat(outer.as(String.class)).isNotPresent(); // Test if FooService.serviceAdded() is invoked. final ServiceConfig cfg = new ServiceConfig(PathMapping.ofCatchAll(), outer, "foo"); outer.serviceAdded(cfg); assertThat(inner.cfg).isSameAs(cfg); } @SuppressWarnings("unchecked") private static Class<Service<?, ?>> serviceType(Service<?, ?> service) { return (Class<Service<?, ?>>) service.getClass(); } private static final class FooService implements Service<RpcRequest, RpcResponse> { ServiceConfig cfg; @Override public void serviceAdded(ServiceConfig cfg) throws Exception { this.cfg = cfg; } @Override public RpcResponse serve(ServiceRequestContext ctx, RpcRequest req) throws Exception { // Will never reach here. throw new Error(); } } public static class FooServiceDecorator extends SimpleDecoratingService<RpcRequest, RpcResponse> { public FooServiceDecorator(Service<? super RpcRequest, ? extends RpcResponse> delegate) { super(delegate); } @Override public RpcResponse serve(ServiceRequestContext ctx, RpcRequest req) throws Exception { return delegate().serve(ctx, req); } } public static class BadFooServiceDecorator extends FooServiceDecorator { public BadFooServiceDecorator(Service<? super RpcRequest, ? extends RpcResponse> delegate, @SuppressWarnings("unused") Object unused) { super(delegate); } } }