/*
 * Copyright 2018, 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.server.entity;

import com.google.protobuf.StringValue;
import com.google.protobuf.Timestamp;
import io.spine.base.Time;
import io.spine.server.model.ModelError;
import io.spine.test.TimeTests;
import io.spine.time.Interval;
import io.spine.time.Intervals;
import org.junit.Test;

import java.lang.reflect.Constructor;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

/**
 * @author Alexander Yevsyukov
 */
public class EntityClassShould {

    private final EntityClass<NanoEntity> entityClass = new EntityClass<>(
            (Class<? extends NanoEntity>) NanoEntity.class);

    @Test
    public void return_id_class() {
        @SuppressWarnings("unchecked") //
        final Class<Long> actual = (Class<Long>) entityClass.getIdClass();
        assertEquals(Long.class, actual);
    }

    @Test
    public void obtain_entity_constructor() {
        final Constructor<NanoEntity> ctor = entityClass.getConstructor();
        assertNotNull(ctor);
    }

    @Test
    public void create_and_initialize_entity_instance() {
        final Long id = 100L;
        final Timestamp before = TimeTests.Past.secondsAgo(1);

        // Create and init the entity.
        final EntityClass<NanoEntity> entityClass = new EntityClass<>(NanoEntity.class);
        final AbstractVersionableEntity<Long, StringValue> entity = entityClass.createEntity(id);

        final Timestamp after = Time.getCurrentTime();

        // The interval with a much earlier start to allow non-zero interval on faster computers.
        final Interval whileWeCreate = Intervals.between(before, after);

        assertEquals(id, entity.getId());
        assertEquals(0, entity.getVersion()
                              .getNumber());
        assertTrue(Intervals.contains(whileWeCreate, entity.whenModified()));
        assertEquals(StringValue.getDefaultInstance(), entity.getState());
        assertFalse(entity.isArchived());
        assertFalse(entity.isDeleted());
    }

    @Test(expected = ModelError.class)
    public void complain_when_there_is_no_one_arg_constructor_for_entity_class() {
        new EntityClass<>(NoArgEntity.class).getConstructor();
    }


    /** A test entity which defines ID and state. */
    private static class NanoEntity extends AbstractVersionableEntity<Long, StringValue> {
        private NanoEntity(Long id) {
            super(id);
        }
    }

    /** An entity class without ID constructor. */
    private static class NoArgEntity extends AbstractEntity<Long, StringValue> {

        private NoArgEntity() {
            super(0L);
        }
    }
}

@@ -1297,20 +1297,85 @@
 g.junit.
-Test
+Rule;%0Aimport org.junit.Test;%0Aimport org.junit.rules.ExpectedException
 ;%0A%0Aimpor
@@ -1707,32 +1707,44 @@
 y%3E entityClass =
+%0A           
  new EntityClass
@@ -1746,29 +1746,16 @@
 Class%3C%3E(
-%0A            
 (Class%3C?
@@ -1792,24 +1792,103 @@
 ty.class);%0A%0A
+    @Rule%0A    public ExpectedException thrown = ExpectedException.none();%0A    %0A
     @Test%0A  
@@ -1971,22 +1971,16 @@
         
-final 
 Class%3CLo
@@ -2145,22 +2145,16 @@
         
-final 
 Construc
@@ -2318,22 +2318,16 @@
         
-final 
 Long id 
@@ -2334,38 +2334,32 @@
 = 100L;%0A        
-final 
 Timestamp before
@@ -2439,22 +2439,16 @@
         
-final 
 EntityCl
@@ -2522,22 +2522,16 @@
         
-final 
 Abstract
@@ -2615,22 +2615,16 @@
         
-final 
 Timestam
@@ -2763,22 +2763,16 @@
         
-final 
 Interval
@@ -3210,37 +3210,8 @@
 Test
-(expected = ModelError.class)
 %0A   
@@ -3282,32 +3282,73 @@
 ntity_class() %7B%0A
+        thrown.expect(ModelError.class);%0A
         new Enti

Handle ignored return values