/*
 * 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.
 *
 * Copyright 2012-2019 the original author or authors.
 */
package org.assertj.core.internal.classes;

import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.error.ShouldHaveMethods.shouldHaveMethods;
import static org.assertj.core.error.ShouldHaveMethods.shouldNotHaveMethods;
import static org.assertj.core.test.TestData.someInfo;
import static org.assertj.core.util.Arrays.array;
import static org.assertj.core.util.FailureMessages.actualIsNull;
import static org.assertj.core.util.Sets.newTreeSet;

import org.assertj.core.internal.ClassesBaseTest;
import org.assertj.core.util.Strings;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class Classes_assertHasMethods_Test extends ClassesBaseTest {

  @BeforeEach
  public void setupActual() {
    AnotherMethodsClass m = new AnotherMethodsClass();
    Strings.isNullOrEmpty(m.string); // causes a synthetic method in AnotherMethodsClass
    actual = AnotherMethodsClass.class;
  }

  private static class AnotherMethodsClass extends MethodsClass {
    private String string;
  }

  @Test
  public void should_pass_if_actual_has_expected_accessible_public_methods() {
    classes.assertHasMethods(someInfo(), actual, "publicMethod", "protectedMethod", "privateMethod");
  }

  @Test
  public void should_fail_if_no_methods_are_expected_and_methods_are_available() {
    assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> classes.assertHasMethods(someInfo(), actual))
                                                   .withMessage(format(shouldNotHaveMethods(actual, false,
                                                                                            newTreeSet("publicMethod",
                                                                                                       "protectedMethod",
                                                                                                       "privateMethod",
                                                                                                       "finalize",
                                                                                                       "wait", "equals",
                                                                                                       "toString",
                                                                                                       "hashCode",
                                                                                                       "getClass",
                                                                                                       "clone",
                                                                                                       "registerNatives",
                                                                                                       "notify",
                                                                                                       "notifyAll")).create()));
  }

  @Test
  public void should_fail_if_actual_is_null() {
    actual = null;
    assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> classes.assertHasMethods(someInfo(), actual))
                                                   .withMessage(actualIsNull());
  }

  @Test
  public void should_pass_if_methods_are_inherited() {
    String[] expected = array("notify", "notifyAll");
    classes.assertHasMethods(someInfo(), actual, expected);
  }

  @Test()
  public void should_fail_if_expected_methods_are_missing() {
    String[] expected = array("missingMethod", "publicMethod");
    assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> classes.assertHasMethods(someInfo(), actual,
                                                                                              expected))
                                                   .withMessage(format(shouldHaveMethods(actual, false,
                                                                                         newTreeSet(expected),
                                                                                         newTreeSet("missingMethod")).create()));
  }
}

@@ -1012,16 +1012,103 @@
 .array;%0A
+import static org.assertj.core.util.AssertionsUtil.assertThatAssertionErrorIsThrownBy;%0A
 import s
@@ -1219,16 +1219,74 @@
 eeSet;%0A%0A
+import java.math.BigDecimal;%0Aimport java.util.SortedSet;%0A%0A
 import o
@@ -2136,622 +2136,205 @@
     
-assertThatExceptionOfType(AssertionError.class).isThrownBy(() -%3E classes.assertHasMethods(someInfo(), actual))%0A                                                   .withMessage(format(shouldNotHaveMethods(actual, false,%0A                                                                                            newTreeSet(%22publicMethod%22,%0A                                                                                                       %22protectedMethod%22,%0A                                                                                                       %22privateMethod%22,%0A                                   
+SortedSet%3CString%3E expectedMethods = newTreeSet(%22publicMethod%22,%0A                                                 %22protectedMethod%22,%0A                                                 %22privateMethod%22,%0A
     
@@ -2378,35 +2378,16 @@
         
-                   
 %22finaliz
@@ -2431,33 +2431,40 @@
                 
- 
+%22wait%22,%0A
                 
@@ -2495,28 +2495,16 @@
         
-     %22wait%22,
  %22equals
@@ -2547,37 +2547,44 @@
                 
-     
+%22toString%22,%0A
                 
@@ -2613,32 +2613,32 @@
            %22
-toString
+hashCode
 %22,%0A         
@@ -2669,32 +2669,44 @@
                 
+%22getClass%22,%0A
                 
@@ -2734,37 +2734,29 @@
             
-     %22hashCod
+%22clon
 e%22,%0A        
@@ -2788,32 +2788,42 @@
                 
+%22notify%22,%0A
                 
@@ -2859,38 +2859,200 @@
     
-     %22getClass%22,
+%22notifyAll%22);%0A    if (isJavaVersionBefore14()) %7B%0A      expectedMethods.add(%22registerNatives%22);
 %0A    
+%7D%0A
     
-     
+assertThatAssertionErrorIsThrownBy(() -%3E classes.assertHasMethods(someInfo(), actual))%0A
     
@@ -3129,39 +3129,79 @@
                 
-%22clone%22
+.withMessage(format(shouldNotHaveMethods(actual
 ,%0A              
@@ -3289,33 +3289,49 @@
         
-%22registerNatives%22
+                            false
 ,%0A      
@@ -3397,52 +3397,8 @@
     
-                                  %22notify%22,%0A
     
@@ -3459,61 +3459,23 @@
     
-                                         %22notifyAll%22)
+expectedMethods
 ).cr
@@ -4650,11 +4650,222 @@
 )));%0A  %7D
+%0A%0A  private static boolean isJavaVersionBefore14() %7B%0A    BigDecimal javaVersion = new BigDecimal(System.getProperty(%22java.specification.version%22));%0A    return javaVersion.compareTo(new BigDecimal(%2214%22)) %3C 0;%0A  %7D
 %0A%7D%0A

Fix Classes_assertHasMethods_Test#should_fail_if_no_methods_are_expected_and_methods_are_available on Java 14+.