Package com.facebook.testing

Source Code of com.facebook.testing.TestUtils

/*
* Copyright (C) 2012 Facebook, Inc.
*
* 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 com.facebook.testing;


import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.testng.Assert;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;

import static org.testng.Assert.assertEquals;

public class TestUtils {
  private TestUtils() {
    throw new AssertionError();
  }

  public static <T> Function<T> noOpFunction() {
    return new Function<T>() {
      @Override
      public void execute(T argument) {
        // noting
      }
    };
  }


  public static AtomicInteger countCompletedRunnables(
    int numTasks, Function<Runnable> submissionCallback
  ) {
    final AtomicInteger completed = new AtomicInteger(0);

    for (int i = 0; i < numTasks; i++) {
      submissionCallback.execute(
        new Runnable() {
          @Override
          public void run() {
            completed.incrementAndGet();
          }
        }
      );
    }

    return completed;
  }

  public static <V> AtomicInteger countCompletedCallables(
    int numTasks, Function<Callable<V>> submissionCallback
  ) {
    final AtomicInteger completed = new AtomicInteger(0);

    for (int i = 0; i < numTasks; i++) {
      submissionCallback.execute(
        new Callable<V>() {
          @Override
          public V call() throws Exception {
            completed.incrementAndGet();

            return null;
          }
        }
      );
    }

    return completed;
  }

  public static String generateString(int start, int length) {
    try {
      return new String(generateSequentialBytes(start, length), "UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }

  public static byte[] generateSequentialBytes(int start, int length) {
    byte[] result = new byte[length];

    for (int i = 0; i < length; i++) {
      result[i] = (byte) ((start + i) % 127);
    }

    return result;
  }

  /**
   * a bit hackish, we wait until the thread is not runnable or new to indicate
   * that is is blocked on a lock or monitor
   *
   * @param t thread to wait for
   */
  public static void waitUntilThreadBlocks(Thread t) {
    Thread.State state = t.getState();

    while (true) {
      switch (state) {
        case NEW:
        case RUNNABLE:
          state = t.getState();
          continue;
        case TERMINATED:
        case BLOCKED:
        case TIMED_WAITING:
        case WAITING:
          return;
      }
    }
  }

  public static Thread runInThread(Runnable runnable) {
    return runInThread(runnable, null);
  }

  public static Thread runInThread(Runnable runnable, String threadName) {
    Thread t = new Thread(runnable);

    if (threadName != null) {
      t.setName(threadName);
    }

    t.start();

    return t;
  }

  /**
   * generate count distinct moments in time, 1 second apart, then randomly order them
   *
   * @param baseDateTime start moment
   * @param count        how many moments to generate
   * @return
   */
  public static List<DateTime> generateMoments(DateTime baseDateTime, int count) {
    List<DateTime> result = new ArrayList<DateTime>(count);

    for (int i = 0; i < count; i++) {
      result.add(baseDateTime.plusSeconds(i));
    }
    Collections.shuffle(result);

    return result;
  }

  /**
   * Returns a set of timezones that are distinct form each other in the kind of offsets they
   * have from UTC.
   * Note: This method returns timezones having the same offsets but are different in that they
   * have fixed or non-fixed offsets. However, it's possible that two timezones with non-fixed
   * offsets have different transitions, only one of such timezones will be returned here.
   */
  public static Collection<DateTimeZone> getDistinctTimeZones() {
    Multimap<Integer, DateTimeZone> timeZones = LinkedHashMultimap.create();
    // figure out a set of timezones with unique offsets
    for (Object obj : DateTimeZone.getAvailableIDs()) {
      String id = (String) obj;
      DateTimeZone dateTimeZone = DateTimeZone.forID(id);
      TimeZone timeZone = dateTimeZone.toTimeZone();
      timeZones.put(timeZone.getRawOffset(), dateTimeZone);
      timeZones.put(timeZone.getRawOffset() + timeZone.getDSTSavings(), dateTimeZone);
    }
    Set<DateTimeZone> distinctZones = new HashSet<DateTimeZone>();
    for (Map.Entry<Integer, Collection<DateTimeZone>> entry : timeZones.asMap().entrySet()) {
      DateTimeZone fixedZone = null;
      DateTimeZone unfixedZone = null;
      for (DateTimeZone timeZone : entry.getValue()) {
        if (timeZone.isFixed()) {
          if (fixedZone == null) {
            fixedZone = timeZone;
          }
        } else {
          if (unfixedZone == null) {
            unfixedZone = timeZone;
          }
        }
      }
      // Collect one instance each of fixed and non-fixed timezones
      if (fixedZone != null) {
        distinctZones.add(fixedZone);
      }
      if (unfixedZone != null) {
        distinctZones.add(unfixedZone);
      }
    }
    return distinctZones;
  }

  public static void assertContains(String haystack, Object needle) {
    Assert.assertTrue(
      haystack != null && haystack.contains(String.valueOf(needle)),
      String.format("Expected to find '%s' in: %s", needle, haystack)
    );
  }

  /**
   * Same as TestNG's {@link Assert#assertEquals(Object, Object)} except the message text is
   * guaranteed to use the {@link Object#toString()} of the objects. Useful for short maps and lists
   * where seeing all the elements is more useful than just the one differing element or size
   * difference.
   *
   * @param actual
   * @param expected
   */
  public static void assertEqualsWithNiceMessage(Object actual, Object expected) {
    assertEqualsWithNiceMessage(actual, expected, null);
  }

  /**
   * Same as TestNG's {@link Assert#assertEquals(Object, Object)} except the message text is
   * guaranteed to use the {@link Object#toString()} of the objects. Useful for short maps and lists
   * where seeing all the elements is more useful than just the one differing element or size
   * difference.
   *
   * @param actual   actual value
   * @param expected expected value
   * @param message  custom message to prepend to default message
   */
  public static void assertEqualsWithNiceMessage(Object actual, Object expected, String message) {
    message = message == null ? "" : (message + " ");

    // using the same formatting as Assert.format() makes Idea do nice UI things (e.g., "Click to
    // see difference")
    assertEquals(
      actual,
      expected,
      message + "expected:<" + expected + "> but was:<" + actual + ">"
    );
  }
}
TOP

Related Classes of com.facebook.testing.TestUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.