com.facebook.buck.testutil.MoreAsserts.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.testutil.MoreAsserts.java

Source

/*
 * Copyright 2012-present 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.buck.testutil;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.shell.ShellStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;

import org.junit.Assert;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * Additional assertions that delegate to JUnit assertions, but with better error messages.
 */
public final class MoreAsserts {

    private MoreAsserts() {
    }

    /**
     * Asserts that two sets have the same contents.
     * On failure, prints a readable diff of the two sets for easy debugging.
     */
    public static <E> void assertSetEquals(Set<E> expected, Set<E> actual) {
        Set<E> missing = Sets.difference(expected, actual);
        Set<E> extra = Sets.difference(actual, expected);
        boolean setsEqual = missing.isEmpty() && extra.isEmpty();
        Assert.assertTrue(String.format("%nMissing elements:%n%s%nExtraneous elements:%n%s", missing, extra),
                setsEqual);
    }

    /**
     * Asserts that two sets have the same contents.
     * On failure, prints a readable diff of the two sets for easy debugging.
     */
    public static <E> void assertSetEquals(String userMessage, Set<E> expected, Set<E> actual) {
        Set<E> missing = Sets.difference(expected, actual);
        Set<E> extra = Sets.difference(actual, expected);
        boolean setsEqual = missing.isEmpty() && extra.isEmpty();
        Assert.assertTrue(
                String.format("%s %nMissing elements:%n%s%nExtraneous elements:%n%s", userMessage, missing, extra),
                setsEqual);
    }

    /**
     * @see #assertIterablesEquals(Iterable, Iterable)
     */
    public static <T extends List<?>> void assertListEquals(List<?> expected, List<?> observed) {
        assertIterablesEquals(expected, observed);
    }

    /**
     * @see #assertIterablesEquals(String, Iterable, Iterable)
     */
    public static <T extends List<?>> void assertListEquals(String userMessage, List<?> expected,
            List<?> observed) {
        assertIterablesEquals(userMessage, expected, observed);
    }

    /**
     * Equivalent to {@link org.junit.Assert#assertEquals(Object, Object)} except if the assertion
     * fails, the message includes information about where the iterables differ.
     */
    public static <T extends Iterable<?>> void assertIterablesEquals(Iterable<?> expected, Iterable<?> observed) {
        assertIterablesEquals(null /* userMessage */, expected, observed);
    }

    /**
     * Equivalent to {@link org.junit.Assert#assertEquals(String, Object, Object)} except if the
     * assertion fails, the message includes information about where the iterables differ.
     */
    public static <T extends Iterable<?>> void assertIterablesEquals(String userMessage, Iterable<?> expected,
            Iterable<?> observed) {
        // The traditional assertEquals() method should be fine if either List is null.
        if (expected == null || observed == null) {
            assertEquals(userMessage, expected, observed);
            return;
        }

        // Compare each item in the list, one at a time.
        Iterator<?> expectedIter = expected.iterator();
        Iterator<?> observedIter = observed.iterator();
        int index = 0;
        while (expectedIter.hasNext()) {
            if (!observedIter.hasNext()) {
                fail(prefixWithUserMessage(userMessage,
                        "Item " + index + " does not exist in the " + "observed list"));
            }
            Object expectedItem = expectedIter.next();
            Object observedItem = observedIter.next();
            assertEquals(prefixWithUserMessage(userMessage, "Item " + index + " in the lists should match."),
                    expectedItem, observedItem);
            ++index;
        }
        if (observedIter.hasNext()) {
            fail(prefixWithUserMessage(userMessage, "Extraneous item " + index + " in the observed list"));
        }
    }

    public static <Item, Container extends Iterable<Item>> void assertContainsOne(Container container,
            Item expectedItem) {
        assertContainsOne(/* userMessage */ null, container, expectedItem);
    }

    public static <Item, Container extends Iterable<Item>> void assertContainsOne(String userMessage,
            Container container, Item expectedItem) {
        int seen = 0;
        for (Item item : container) {
            if (expectedItem.equals(item)) {
                seen++;
            }
        }
        if (seen < 1) {
            failWith(userMessage, "Item '" + expectedItem + "' not found in container, " + "expected to find one.");
        }
        if (seen > 1) {
            failWith(userMessage, "Found " + Integer.valueOf(seen) + " occurrences of '" + expectedItem
                    + "' in container, expected to find only one.");
        }
    }

    /**
     * Asserts that every {@link com.facebook.buck.step.Step} in the observed list is a
     * {@link com.facebook.buck.shell.ShellStep} whose shell
     * command arguments match those of the corresponding entry in the expected list.
     */
    public static void assertShellCommands(String userMessage, List<String> expected, List<Step> observed,
            ExecutionContext context) {
        Iterator<String> expectedIter = expected.iterator();
        Iterator<Step> observedIter = observed.iterator();
        Joiner joiner = Joiner.on(" ");
        while (expectedIter.hasNext() && observedIter.hasNext()) {
            String expectedShellCommand = expectedIter.next();
            Step observedStep = observedIter.next();
            if (!(observedStep instanceof ShellStep)) {
                failWith(userMessage, "Observed command must be a shell command: " + observedStep);
            }
            ShellStep shellCommand = (ShellStep) observedStep;
            String observedShellCommand = joiner.join(shellCommand.getShellCommand(context));
            assertEquals(userMessage, expectedShellCommand, observedShellCommand);
        }

        if (expectedIter.hasNext()) {
            failWith(userMessage, "Extra expected command: " + expectedIter.next());
        }

        if (observedIter.hasNext()) {
            failWith(userMessage, "Extra observed command: " + observedIter.next());
        }
    }

    /**
     * Invokes the {@link Step#getDescription(ExecutionContext)} method on each of the observed steps
     * to create a list of strings and compares it to the expected value.
     */
    public static void assertSteps(String userMessage, List<String> expectedStepDescriptions,
            List<Step> observedSteps, final ExecutionContext executionContext) {
        ImmutableList<String> commands = FluentIterable.from(observedSteps).transform(new Function<Step, String>() {
            @Override
            public String apply(Step step) {
                return step.getDescription(executionContext);
            }
        }).toList();
        assertListEquals(userMessage, expectedStepDescriptions, commands);
    }

    public static void assertDepends(String userMessage, BuildRule rule, BuildRule dep) {
        assertDepends(userMessage, rule, dep.getBuildTarget());
    }

    public static void assertDepends(String userMessage, BuildRule rule, BuildTarget dep) {
        assertDepends(userMessage, rule.getDeps(), dep);
    }

    public static void assertDepends(String userMessage, Collection<BuildRule> ruleDeps, BuildTarget dep) {
        for (BuildRule realDep : ruleDeps) {
            BuildTarget target = realDep.getBuildTarget();
            if (target.equals(dep)) {
                return;
            }
        }
        fail(userMessage);
    }

    public static void assertNotDepends(String userMessage, BuildRule rule, BuildTarget dep) {
        assertNotDepends(userMessage, rule.getDeps(), dep);
    }

    public static void assertNotDepends(String userMessage, Collection<BuildRule> ruleDeps, BuildTarget dep) {
        for (BuildRule realDep : ruleDeps) {
            BuildTarget target = realDep.getBuildTarget();
            if (target.equals(dep)) {
                fail(userMessage);
            }
        }
    }

    public static <T> void assertOptionalValueEquals(String userMessage, T expectedValue,
            Optional<T> optionalValue) {
        if (!optionalValue.isPresent()) {
            failWith(userMessage, "Optional value is not present.");
        }

        assertEquals(userMessage, expectedValue, optionalValue.get());
    }

    private static String prefixWithUserMessage(@Nullable String userMessage, String message) {
        return (userMessage == null ? "" : userMessage + " ") + message;
    }

    private static void failWith(@Nullable String userMessage, String message) {
        fail(prefixWithUserMessage(userMessage, message));
    }
}