content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF 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.
   */
  package org.apache.cassandra.net;
  
  import java.net.UnknownHostException;
  import java.util.function.Predicate;
  
  import org.apache.cassandra.locator.InetAddressAndPort;
  
  /**
   * Starting point for mocking {@link MessagingService} interactions. Outgoing messages can be
   * intercepted by first creating a {@link MatcherResponse} by calling {@link MockMessagingService#when(Matcher)}.
   * Alternatively {@link Matcher}s can be created by using helper methods such as {@link #to(InetAddressAndPort)},
   * {@link #verb(Verb)} or {@link #payload(Predicate)} and may also be
   * nested using {@link MockMessagingService#all(Matcher[])} or {@link MockMessagingService#any(Matcher[])}.
   * After each test, {@link MockMessagingService#cleanup()} must be called for free listeners registered
   * in {@link MessagingService}.
   */
  public class MockMessagingService
  {
  
      private MockMessagingService()
      {
      }
  
      /**
       * Creates a MatcherResponse based on specified matcher.
       */
      public static MatcherResponse when(Matcher matcher)
      {
          return new MatcherResponse(matcher);
      }
  
      /**
       * Unsubscribes any handlers.
       * This should be called after each test.
       */
      public static void cleanup()
      {
          MessagingService.instance().outboundSink.clear();
          MessagingService.instance().inboundSink.clear();
      }
  
      /**
       * Creates a matcher that will indicate if the target address of the outgoing message equals the
       * provided address.
       */
      public static Matcher<InetAddressAndPort> to(String address)
      {
          try
          {
              return to(InetAddressAndPort.getByName(address));
          }
          catch (UnknownHostException e)
          {
              throw new RuntimeException(e);
          }
      }
  
      /**
       * Creates a matcher that will indicate if the target address of the outgoing message equals the
       * provided address.
       */
      public static Matcher<InetAddressAndPort> to(InetAddressAndPort address)
      {
          return (in, to) -> to == address || to.equals(address);
      }
  
      /**
       * Creates a matcher that will indicate if the target address of the outgoing message matches the provided predicate.
       */
      public static Matcher<InetAddressAndPort> to(Predicate<InetAddressAndPort> predicate)
      {
          return (in, to) -> predicate.test(to);
      }
  
      /**
       * Creates a matcher that will indicate if the verb of the outgoing message equals the
       * provided value.
       */
      public static Matcher<Verb> verb(Verb verb)
      {
          return (in, to) -> in.verb() == verb;
      }
  
      /**
       * Creates a matcher based on the result of the provided predicate called with the outgoing message.
       */
      public static <T> Matcher<T> message(Predicate<Message<T>> fn)
      {
          return (msg, to) -> fn.test(msg);
      }
  
      /**
       * Creates a matcher based on the result of the provided predicate called with the outgoing message's payload.
       */
      public static <T> Matcher<T> payload(Predicate<T> fn)
      {
          return (msg, to) -> fn.test(msg.payload);
      }
  
      /**
       * Inverts boolean result of wrapped matcher.
       */
      public static <T> Matcher<T> not(Matcher<T> matcher)
      {
          return (o, to) -> !matcher.matches(o, to);
      }
  
      /**
       * Indicates true in case all provided matchers returned true.
       */
      public static <T> Matcher<?> all(Matcher<?>... matchers)
      {
          return (Message<T> out, InetAddressAndPort to) -> {
              for (Matcher matcher : matchers)
              {
                  if (!matcher.matches(out, to))
                      return false;
              }
              return true;
          };
      }
  
      /**
       * Indicates true in case at least a single provided matcher returned true.
       */
      public static <T> Matcher<?> any(Matcher<?>... matchers)
      {
          return (Message<T> out, InetAddressAndPort to) -> {
              for (Matcher matcher : matchers)
              {
                  if (matcher.matches(out, to))
                      return true;
              }
              return false;
          };
      }
  }
  