/*
 * 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 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 testLambdaExpressionDecorator() 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);
        });

        // 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();
        }
    }
}

@@ -722,16 +722,82 @@
 ertThat;
+%0Aimport static org.assertj.core.api.Assertions.assertThatThrownBy;
 %0A%0Aimport
@@ -1097,13 +1097,9 @@
 oid 
-testL
+l
 ambd
@@ -1447,24 +1447,658 @@
        %7D);%0A%0A
+        assertDecoration(inner, outer);%0A    %7D%0A%0A    /**%0A     * Tests %7B@link Service#decorate(Class)%7D.%0A     */%0A    @Test%0A    public void reflectionDecorator() throws Exception %7B%0A        final FooService inner = new FooService();%0A        final FooServiceDecorator outer = inner.decorate(FooServiceDecorator.class);%0A%0A        assertDecoration(inner, outer);%0A        assertThatThrownBy(() -%3E inner.decorate(BadFooServiceDecorator.class))%0A                .isInstanceOf(IllegalArgumentException.class);%0A    %7D%0A%0A    private static void assertDecoration(%0A            FooService inner, Service%3CRpcRequest, RpcResponse%3E outer) throws Exception %7B%0A%0A
         // T
@@ -3144,16 +3144,16 @@
 h here.%0A
-
         
@@ -3190,11 +3190,734 @@
  %7D%0A    %7D
+%0A%0A    public static class FooServiceDecorator extends SimpleDecoratingService%3CRpcRequest, RpcResponse%3E %7B%0A        public FooServiceDecorator(Service%3C? super RpcRequest, ? extends RpcResponse%3E delegate) %7B%0A            super(delegate);%0A        %7D%0A%0A        @Override%0A        public RpcResponse serve(ServiceRequestContext ctx, RpcRequest req) throws Exception %7B%0A            return delegate().serve(ctx, req);%0A        %7D%0A    %7D%0A%0A    public static class BadFooServiceDecorator extends FooServiceDecorator %7B%0A        public BadFooServiceDecorator(Service%3C? super RpcRequest, ? extends RpcResponse%3E delegate,%0A                                      @SuppressWarnings(%22unused%22) Object unused) %7B%0A            super(delegate);%0A        %7D%0A    %7D
 %0A%7D%0A

Add more test case to ServiceTest (#501)