/*
 * Licensed to Crate.io GmbH ("Crate") under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.  Crate licenses
 * this file to you 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.
 *
 * However, if you have executed another commercial license agreement
 * with Crate these terms will supersede the license and you may use the
 * software solely pursuant to the terms of the relevant commercial agreement.
 */

package io.crate.planner;

import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.Nullable;

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

import io.crate.data.BatchIterator;
import io.crate.data.Row;
import io.crate.data.RowConsumer;
import io.crate.planner.node.management.ExplainPlan;
import io.crate.planner.operators.SubQueryResults;
import io.crate.test.integration.CrateDummyClusterServiceUnitTest;
import io.crate.testing.SQLExecutor;

public class ExplainPlannerTest extends CrateDummyClusterServiceUnitTest {

    private static final List<String> EXPLAIN_TEST_STATEMENTS = List.of(
        "select 1 as connected",
        "select id from sys.cluster",
        "select id from users order by id",
        "select * from users",
        "select count(*) from users",
        "select name, count(distinct id) from users group by name",
        "select avg(id) from users",
        "select * from users where name = (select 'name')"
    );

    private SQLExecutor e;

    @Before
    public void prepare() throws IOException {
        e = SQLExecutor.builder(clusterService).enableDefaultTables().build();
    }

    @Test
    public void testExplain() {
        for (String statement : EXPLAIN_TEST_STATEMENTS) {
            ExplainPlan plan = e.plan("EXPLAIN " + statement);
            assertNotNull(plan);
            assertNotNull(plan.subPlan());
            assertFalse(plan.doAnalyze());
        }
    }

    @Test
    public void testExplainAnalyze() {
        for (String statement : EXPLAIN_TEST_STATEMENTS) {
            ExplainPlan plan = e.plan("EXPLAIN ANALYZE " + statement);
            assertNotNull(plan);
            assertNotNull(plan.subPlan());
            assertTrue(plan.doAnalyze());
        }
    }


    @Test
    public void testExplainAnalyzeMultiPhasePlanNotSupported() {
        ExplainPlan plan = e.plan("EXPLAIN ANALYZE SELECT * FROM users WHERE name = (SELECT 'crate') or id = (SELECT 1)");
        PlannerContext plannerContext = e.getPlannerContext(clusterService.state());
        CountDownLatch counter = new CountDownLatch(1);

        AtomicReference<BatchIterator<Row>> itRef = new AtomicReference<>();
        AtomicReference<Throwable> failureRef = new AtomicReference<>();

        plan.execute(null, plannerContext, new RowConsumer() {
            @Override
            public void accept(BatchIterator<Row> iterator, @Nullable Throwable failure) {
                itRef.set(iterator);
                failureRef.set(failure);
                counter.countDown();
            }

            @Override
            public CompletableFuture<?> completionFuture() {
                return null;
            }
        }, Row.EMPTY, SubQueryResults.EMPTY);

        assertNull(itRef.get());
        assertNotNull(failureRef.get());
        assertThat(failureRef.get().getMessage(), containsString("EXPLAIN ANALYZE does not support profiling multi-phase plans, such as queries with scalar subselects."));
    }
}

@@ -1055,259 +1055,46 @@
 org.
-hamcrest.Matchers.containsString;%0Aimport static org.junit.Assert.assertFalse;%0Aimport static org.junit.Assert.assertNotNull;%0Aimport static org.junit.Assert.assertNull;%0Aimport static org.junit.Assert.assertThat;%0Aimport static org.junit.Assert.assertTrue
+assertj.core.api.Assertions.assertThat
 ;%0A%0Ai
@@ -2532,32 +2532,45 @@
       assert
+That(plan).is
 NotNull(
 plan);%0A     
@@ -2549,36 +2549,32 @@
 plan).isNotNull(
-plan
 );%0A            a
@@ -2570,39 +2570,36 @@
           assert
-NotNull
+That
 (plan.subPlan())
@@ -2590,32 +2590,44 @@
 (plan.subPlan())
+.isNotNull()
 ;%0A            as
@@ -2634,13 +2634,12 @@
 sert
-False
+That
 (pla
@@ -2644,32 +2644,42 @@
 lan.doAnalyze())
+.isFalse()
 ;%0A        %7D%0A    
@@ -2874,32 +2874,45 @@
       assert
+That(plan).is
 NotNull(
 plan);%0A     
@@ -2899,20 +2899,16 @@
 NotNull(
-plan
 );%0A     
@@ -2920,23 +2920,20 @@
   assert
-NotNull
+That
 (plan.su
@@ -2940,16 +2940,28 @@
 bPlan())
+.isNotNull()
 ;%0A      
@@ -2977,11 +2977,11 @@
 ertT
-rue
+hat
 (pla
@@ -2990,24 +2990,33 @@
 doAnalyze())
+.isTrue()
 ;%0A        %7D%0A
@@ -4007,20 +4007,20 @@
   assert
-Null
+That
 (itRef.g
@@ -4016,32 +4016,41 @@
 hat(itRef.get())
+.isNull()
 ;%0A        assert
@@ -4049,23 +4049,20 @@
   assert
-NotNull
+That
 (failure
@@ -4071,16 +4071,28 @@
 f.get())
+.isNotNull()
 ;%0A      
@@ -4137,24 +4137,19 @@
 ge()
-, containsString
+).isEqualTo
 (%22EX
@@ -4249,17 +4249,16 @@
 lects.%22)
-)
 ;%0A    %7D%0A

Convert ExplainPlannerTest to assertj