/*
 * Copyright 2016, TeamDev Ltd. 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 org.spine3.protobuf;

import com.google.common.collect.ImmutableSet;
import com.google.protobuf.StringValue;
import org.junit.Test;
import org.spine3.base.Command;
import org.spine3.base.CommandContext;
import org.spine3.protobuf.error.UnknownTypeException;
import org.spine3.type.ClassName;

import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.spine3.protobuf.TypeUrl.composeTypeUrl;
import static org.spine3.test.Tests.hasPrivateUtilityConstructor;

/**
 * @author Alexander Litus
 */
@SuppressWarnings("InstanceMethodNamingConvention")
public class KnownTypesShould {

    // TODO:2016-08-04:alexander.litus: tests for Spine/google msgs, check that all classes and urls are correct

    @Test
    public void have_private_constructor() {
        assertTrue(hasPrivateUtilityConstructor(KnownTypes.class));
    }

    @Test
    public void return_known_proto_message_types() {
        final ImmutableSet<TypeUrl> types = KnownTypes.getTypeNames();

        assertFalse(types.isEmpty());
    }

    @Test
    public void return_java_class_name_by_proto_type_url() {
        final TypeUrl typeUrl = TypeUrl.of(Command.getDescriptor());

        final ClassName className = KnownTypes.getClassName(typeUrl);

        assertEquals(ClassName.of(Command.class), className);
    }

    @Test
    public void return_java_inner_class_name_by_proto_type_url() {
        final TypeUrl typeUrl = TypeUrl.of(CommandContext.Schedule.getDescriptor());

        final ClassName className = KnownTypes.getClassName(typeUrl);

        assertEquals(ClassName.of(CommandContext.Schedule.class), className);
    }

    @Test
    public void return_proto_type_url_by_java_class_name() {
        final ClassName className = ClassName.of(Command.class);

        final TypeUrl typeUrl = KnownTypes.getTypeUrl(className);

        assertEquals(TypeUrl.of(Command.getDescriptor()), typeUrl);
    }

    @Test
    public void return_proto_type_url_by_proto_type_name() {
        final TypeUrl typeUrlExpected = TypeUrl.of(StringValue.getDescriptor());

        final TypeUrl typeUrlActual = KnownTypes.getTypeUrl(typeUrlExpected.getTypeName());

        assertEquals(typeUrlExpected, typeUrlActual);
    }

    @Test
    public void have_all_valid_java_class_names() {
        final Set<ClassName> classes = KnownTypes.getJavaClasses();
        assertFalse(classes.isEmpty());
        for (ClassName name : classes) {
            try {
                Class.forName(name.value());
            } catch (ClassNotFoundException e) {
                fail("Invalid Java class name in the '.properties' file: " + name.value());
            }
        }
    }

    @Test(expected = IllegalStateException.class)
    public void throw_exception_if_no_proto_type_url_by_java_class_name() {
        KnownTypes.getTypeUrl(ClassName.of(Exception.class));
    }

    @Test(expected = UnknownTypeException.class)
    public void throw_exception_if_no_java_class_name_by_type_url() {
        final TypeUrl unexpectedUrl = TypeUrl.of(composeTypeUrl("prefix", "unexpected.type"));
        KnownTypes.getClassName(unexpectedUrl);
    }
}

@@ -1114,27 +1114,204 @@
 rotobuf.
-StringValue
+Any;%0Aimport com.google.protobuf.Duration;%0Aimport com.google.protobuf.Empty;%0Aimport com.google.protobuf.Message;%0Aimport com.google.protobuf.StringValue;%0Aimport com.google.protobuf.Timestamp
 ;%0Aimport
@@ -1398,16 +1398,83 @@
 ontext;%0A
+import org.spine3.base.Event;%0Aimport org.spine3.base.EventContext;%0A
 import o
@@ -1996,122 +1996,8 @@
  %7B%0A%0A
-    // TODO:2016-08-04:alexander.litus: tests for Spine/google msgs, check that all classes and urls are correct%0A%0A
     
@@ -2331,24 +2331,30 @@
 void return_
+spine_
 java_class_n
@@ -2348,32 +2348,33 @@
 _java_class_name
+s
 _by_proto_type_u
@@ -2367,32 +2367,33 @@
 y_proto_type_url
+s
 () %7B%0A        fin
@@ -2393,66 +2393,743 @@
     
-final TypeUrl typeUrl = TypeUrl.of(Command.getDescriptor()
+assertHasClassNameByTypeUrlOf(Command.class);%0A        assertHasClassNameByTypeUrlOf(CommandContext.class);%0A        assertHasClassNameByTypeUrlOf(Event.class);%0A        assertHasClassNameByTypeUrlOf(EventContext.class);%0A        assertHasClassNameByTypeUrlOf(org.spine3.base.Error.class);%0A    %7D%0A%0A    @Test%0A    public void return_google_java_class_names_by_proto_type_urls() %7B%0A        assertHasClassNameByTypeUrlOf(Any.class);%0A        assertHasClassNameByTypeUrlOf(Timestamp.class);%0A        assertHasClassNameByTypeUrlOf(Duration.class);%0A        assertHasClassNameByTypeUrlOf(Empty.class);%0A    %7D%0A%0A    private static void assertHasClassNameByTypeUrlOf(Class%3C? extends Message%3E msgClass) %7B%0A        final TypeUrl typeUrl = TypeUrl.of(msgClass
 );%0A%0A
@@ -3229,33 +3229,28 @@
 lassName.of(
-Command.c
+msgC
 lass), class

Add tests for known types.