/*
 * Copyright 2019, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.testing.server;

import com.google.protobuf.Message;
import io.spine.base.CommandMessage;
import io.spine.base.EventMessage;
import io.spine.server.type.CommandClass;
import io.spine.server.type.EventClass;
import io.spine.type.MessageClass;

import java.util.Collection;
import java.util.function.Function;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * Common assertions for server-side testing.
 */
public final class Assertions {

    /** Prevents instantiation of this utility class. */
    private Assertions() {
    }

    /**
     * Asserts that each of the {@code commandClass} is available in {@code expected}.
     */
    @SafeVarargs
    public static void assertCommandClasses(Collection<CommandClass> expected,
                                            Class<? extends CommandMessage>... commandClass) {
        assertContains(expected, CommandClass::from, commandClass);
    }

    /**
     * Asserts that each of the {@code eventClass} is available in {@code expected}.
     */
    @SafeVarargs
    public static void assertEventClasses(Collection<EventClass> expected,
                                          Class<? extends EventMessage>... eventClass) {
        assertContains(expected, EventClass::from, eventClass);
    }

    @SafeVarargs
    private static <C extends MessageClass, M extends Message>
    void assertContains(Collection<C> expected,
                        Function<Class<M>, C> func,
                        Class<? extends M>...classes) {
        checkNotNull(expected);
        checkNotNull(classes);
        for (Class<? extends M> cls : classes) {
            assertNotNull(cls);
            @SuppressWarnings("unchecked") // OK for tests.
            Class<M> messageType = (Class<M>) cls;
            C messageClass = func.apply(messageType);
            assertTrue(expected.contains(messageClass));
        }
    }
}

@@ -1389,32 +1389,88 @@
 s.checkNotNull;%0A
+import static com.google.common.truth.Truth.assertThat;%0A
 import static or
@@ -1797,22 +1797,24 @@
 the 
-%7B@code
+expected
  command
 Clas
@@ -1809,22 +1809,22 @@
  command
-C
+ c
 lass
-%7D
  is avai
@@ -1832,32 +1832,37 @@
 able in 
-%7B@code expected%7D
+the passed collection
 .%0A     *
@@ -1945,32 +1945,38 @@
 mmandClass%3E 
-expected
+commandClasses
 ,%0A          
@@ -2044,28 +2044,24 @@
 age%3E... 
-commandClass
+expected
 ) %7B%0A    
@@ -2079,24 +2079,30 @@
 ontains(
-expected
+commandClasses
 , Comman
@@ -2115,28 +2115,24 @@
 ::from, 
-commandClass
+expected
 );%0A    %7D
@@ -2177,26 +2177,28 @@
 the 
-%7B@code
+expected
  event
-C
+ c
 lass
-%7D
  is 
@@ -2214,24 +2214,29 @@
  in 
-%7B@code expected%7D
+the passed collection
 .%0A  
@@ -2324,23 +2324,27 @@
 Class%3E e
-xpected
+ventClasses
 ,%0A      
@@ -2413,25 +2413,23 @@
 ge%3E... e
-ventClass
+xpected
 ) %7B%0A    
@@ -2448,23 +2448,27 @@
 ntains(e
-xpected
+ventClasses
 , EventC
@@ -2480,25 +2480,23 @@
 :from, e
-ventClass
+xpected
 );%0A    %7D
@@ -2615,24 +2615,26 @@
 tion%3CC%3E 
-expected
+collection
 ,%0A      
@@ -2756,24 +2756,26 @@
 NotNull(
-expected
+collection
 );%0A     
@@ -3073,51 +3073,921 @@
 rue(
-expected.
+collection.contains(messageClass));%0A        %7D%0A    %7D%0A%0A    /**%0A     * Asserts that passed event classes are exactly as expected.%0A     *%0A     * %3Cp%3EThe order is not taken into ac
 co
+u
 nt
-ains(messageClass));%0A        %7D
+.%0A     */%0A    @SafeVarargs%0A    public static void assertEventClassesExactly(Iterable%3CEventClass%3E eventClasses,%0A                                                 Class%3C? extends EventMessage%3E... expected) %7B%0A        assertThat(eventClasses).containsExactlyElementsIn(EventClass.setOf(expected));%0A    %7D%0A%0A    /**%0A     * Asserts that passed command classes are exactly as expected.%0A     *%0A     * %3Cp%3EThe order is not taken into account.%0A     */%0A    @SafeVarargs%0A    public static void assertCommandClassesExactly(Iterable%3CCommandClass%3E commandClasses,%0A                                                   Class%3C? extends CommandMessage%3E... expected) %7B%0A        assertThat(commandClasses).containsExactlyElementsIn(CommandClass.setOf(expected));
 %0A   

Add utils, fix param names