/*
 * Autosleep
 * Copyright (C) 2016 Orange
 * Authors: Benjamin Einaudi   benjamin.einaudi@orange.com
 *          Arnaud Ruffin      arnaud.ruffin@orange.com
 *
 * 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 org.cloudfoundry.autosleep.worker;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.cloudfoundry.autosleep.util.ApplicationLocker;
import org.junit.Test;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@Slf4j
public class ApplicationLockerTest {

    private ApplicationLocker applicationLocker = spy(new ApplicationLocker());

    @AllArgsConstructor
    private static class SleepingRun implements Runnable {
        private int id;

        private long sleepTime;

        private List<Integer> output;

        @Override
        public void run() {
            try {
                Thread.sleep(sleepTime);
                output.add(id);
            } catch (InterruptedException i) {
                log.debug("passed");
            }
        }
    }

    @AllArgsConstructor
    private static class DryRun implements Runnable {
        private int id;

        private List<Integer> output;

        @Override
        public void run() {
            output.add(id);
        }
    }


    @Test
    public void testExecuteThreadSafe() throws Exception {
        Duration duration = Duration.ofMillis(500);
        ArrayList<Integer> someInts = new ArrayList<>();
        Runnable task1 = spy(new SleepingRun(1, duration.dividedBy(5).toMillis(), someInts));
        Runnable task2 = spy(new DryRun(2, someInts));
        applicationLocker.executeThreadSafe("someId", task1);
        Thread.sleep(duration.dividedBy(10).toMillis());
        applicationLocker.executeThreadSafe("someId", task2);
        Thread.sleep(duration.toMillis());
        verify(task1, times(1)).run();
        verify(task2, times(1)).run();
        assertThat(someInts.size(), is(equalTo(2)));
        assertThat(someInts.get(0), is(equalTo(1)));
        assertThat(someInts.get(1), is(equalTo(2)));
    }

    @Test
    public void testRemoveApplication() throws Exception {
        Runnable task1 = () -> log.debug("passed");
        applicationLocker.executeThreadSafe("someId", task1);
        //call on existing task does not throw exception
        applicationLocker.removeApplication("someId");
        //call again neither
        applicationLocker.removeApplication("someId");
        //Call on non existing neither
        applicationLocker.removeApplication("someOtherId");


    }


}
@@ -2066,25 +2066,43 @@
 test
-E
+_e
 xecute
-T
+_t
 hread
-S
+_s
 afe
+_locks_properly
 () t
@@ -2224,24 +2224,92 @@
 ayList%3C%3E();%0A
+        //Given a task that will wait a little before adding its id%0A
         Runn
@@ -2402,54 +2402,173 @@
     
-Runnable task2 = spy(new DryRun(2, someInts));
+//And another one that will add it immediately%0A        Runnable task2 = spy(new DryRun(2, someInts));%0A        //When we launch the sleeping one before the second one
 %0A   
@@ -2630,65 +2630,8 @@
 1);%0A
-        Thread.sleep(duration.dividedBy(10).toMillis());%0A
     
@@ -2700,42 +2700,32 @@
     
-Thread.sleep(duration.toMillis());
+//Then all tasks are run
 %0A   
@@ -2811,52 +2811,207 @@
     
-assertThat(someInts.size(), is(equalTo(2)));
+//And the ids of task have been inserted in the good order%0A        assertThat(someInts.size(), is(equalTo(2)));%0A        //The first one is the first that called the executeThreadSafe even if it slept
 %0A   
@@ -3056,24 +3056,68 @@
 ualTo(1)));%0A
+        //And the second one is the dry one%0A
         asse
@@ -3198,15 +3198,17 @@
 test
-R
+_r
 emove
-A
+_a
 ppli
@@ -3213,16 +3213,25 @@
 lication
+s_succeed
 () throw
@@ -3288,32 +3288,61 @@
 ebug(%22passed%22);%0A
+        //Given a lock exist%0A
         applicat
@@ -3401,138 +3401,29 @@
   //
-call on existing task does not throw exception%0A        applicationLocker.removeApplication(%22someId%22);%0A        //call again neither
+When we call a remove
 %0A   
@@ -3488,98 +3488,35 @@
   //
-Call o
+The
 n no
-n
  ex
-isting neither%0A        applicationLocker.removeApplication(%22someOtherId%22);%0A%0A
+ception is thrown
 %0A   
@@ -3520,9 +3520,10 @@
     %7D%0A%0A%0A
+%0A
 %7D

Fix #153 : Refactor of ApplicationLockerTest