/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed 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.android.internal.net.ipsec.ike.ike3gpp;

import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.IKE_EXCHANGE_SUBTYPE_IKE_AUTH;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.IKE_EXCHANGE_SUBTYPE_IKE_INIT;
import static com.android.internal.net.ipsec.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_BACKOFF_TIMER;
import static com.android.internal.net.ipsec.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_N1_MODE_CAPABILITY;
import static com.android.internal.net.ipsec.ike.ike3gpp.Ike3gppExtensionExchange.NOTIFY_TYPE_N1_MODE_INFORMATION;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

import android.net.ipsec.ike.ike3gpp.Ike3gppExtension;
import android.net.ipsec.ike.ike3gpp.Ike3gppExtension.Ike3gppCallback;
import android.net.ipsec.ike.ike3gpp.Ike3gppParams;

import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload;
import com.android.internal.net.ipsec.ike.message.IkePayload;
import com.android.internal.util.HexDump;

import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;

public class Ike3gppExtensionExchangeTest {
    private static final byte PDU_SESSION_ID = (byte) 0x01;
    private static final byte[] N1_MODE_CAPABILITY_DATA = HexDump.hexStringToByteArray("0101");

    private static final byte[] N1_MODE_INFORMATION_DATA =
            HexDump.hexStringToByteArray("0411223344");
    private static final byte[] BACKOFF_TIMER_DATA = HexDump.hexStringToByteArray("01AF");

    private static final IkeNotifyPayload N1_MODE_INFORMATION =
            new IkeNotifyPayload(NOTIFY_TYPE_N1_MODE_INFORMATION, N1_MODE_INFORMATION_DATA);
    private static final IkeNotifyPayload FRAGMENTATION_SUPPORTED =
            new IkeNotifyPayload(IkeNotifyPayload.NOTIFY_TYPE_IKEV2_FRAGMENTATION_SUPPORTED);
    private static final IkeNotifyPayload BACKOFF_TIMER =
            new IkeNotifyPayload(NOTIFY_TYPE_BACKOFF_TIMER, BACKOFF_TIMER_DATA);

    private static final Executor INLINE_EXECUTOR = Runnable::run;

    private Ike3gppCallback mMockIke3gppCallback;

    private Ike3gppParams mIke3gppParams;
    private Ike3gppExtensionExchange mIke3gppExtensionExchange;

    @Before
    public void setUp() {
        mMockIke3gppCallback = mock(Ike3gppCallback.class);

        mIke3gppParams = new Ike3gppParams.Builder().setPduSessionId(PDU_SESSION_ID).build();
        mIke3gppExtensionExchange =
                new Ike3gppExtensionExchange(
                        new Ike3gppExtension(mIke3gppParams, mMockIke3gppCallback),
                        INLINE_EXECUTOR);
    }

    @Test
    public void testGetRequestPayloadsIkeAuth() throws Exception {
        List<IkePayload> result =
                mIke3gppExtensionExchange.getRequestPayloads(IKE_EXCHANGE_SUBTYPE_IKE_AUTH);

        assertEquals(1, result.size());

        IkeNotifyPayload n1ModeCapability = (IkeNotifyPayload) result.get(0);
        assertEquals(NOTIFY_TYPE_N1_MODE_CAPABILITY, n1ModeCapability.notifyType);
        assertArrayEquals(N1_MODE_CAPABILITY_DATA, n1ModeCapability.notifyData);
    }

    @Test
    public void testGetRequestPayloadsIkeAuthNotConfigured() throws Exception {
        mIke3gppExtensionExchange = new Ike3gppExtensionExchange(null, INLINE_EXECUTOR);

        List<IkePayload> result =
                mIke3gppExtensionExchange.getRequestPayloads(IKE_EXCHANGE_SUBTYPE_IKE_AUTH);

        assertTrue(result.isEmpty());
    }

    @Test
    public void testGetRequestPayloadsIkeInit() throws Exception {
        List<IkePayload> result =
                mIke3gppExtensionExchange.getRequestPayloads(IKE_EXCHANGE_SUBTYPE_IKE_INIT);

        assertTrue(result.isEmpty());
    }

    @Test
    public void testExtract3gppResponsePayloadsIkeAuth() throws Exception {
        List<IkePayload> result =
                mIke3gppExtensionExchange.extract3gppResponsePayloads(
                        IKE_EXCHANGE_SUBTYPE_IKE_AUTH,
                        Arrays.asList(N1_MODE_INFORMATION, BACKOFF_TIMER, FRAGMENTATION_SUPPORTED));

        assertEquals(2, result.size());

        IkeNotifyPayload n1ModeInformation = null;
        IkeNotifyPayload backoffTimer = null;
        for (IkePayload payload : result) {
            if (payload instanceof IkeNotifyPayload) {
                IkeNotifyPayload notifyPayload = (IkeNotifyPayload) payload;
                if (notifyPayload.notifyType == NOTIFY_TYPE_N1_MODE_INFORMATION) {
                    n1ModeInformation = notifyPayload;
                } else if (notifyPayload.notifyType == NOTIFY_TYPE_BACKOFF_TIMER) {
                    backoffTimer = notifyPayload;
                }
            }
        }

        assertArrayEquals(N1_MODE_INFORMATION_DATA, n1ModeInformation.notifyData);
        assertArrayEquals(BACKOFF_TIMER_DATA, backoffTimer.notifyData);
    }

    @Test
    public void testExtract3gppResponsePayloadsIkeAuthNotConfigured() throws Exception {
        mIke3gppExtensionExchange = new Ike3gppExtensionExchange(null, INLINE_EXECUTOR);

        List<IkePayload> result =
                mIke3gppExtensionExchange.extract3gppResponsePayloads(
                        IKE_EXCHANGE_SUBTYPE_IKE_INIT,
                        Arrays.asList(N1_MODE_INFORMATION, BACKOFF_TIMER, FRAGMENTATION_SUPPORTED));
        assertTrue(result.isEmpty());
    }

    @Test
    public void testExtract3gppResponsePayloadsIkeInit() throws Exception {
        List<IkePayload> result =
                mIke3gppExtensionExchange.extract3gppResponsePayloads(
                        IKE_EXCHANGE_SUBTYPE_IKE_INIT,
                        Arrays.asList(N1_MODE_INFORMATION, BACKOFF_TIMER, FRAGMENTATION_SUPPORTED));
        assertTrue(result.isEmpty());
    }

    @Test
    public void testExtract3gppResponsePayloadsIkeAuthNo3gpp() throws Exception {
        List<IkePayload> result =
                mIke3gppExtensionExchange.extract3gppResponsePayloads(
                        IKE_EXCHANGE_SUBTYPE_IKE_AUTH, Arrays.asList(FRAGMENTATION_SUPPORTED));
        assertTrue(result.isEmpty());
    }
}
