blob: c7da2ad49a04b0ed1bf06ccccfeaa848c5852198 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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.intellij.openapi.vcs;
import com.intellij.notification.Notification;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.*;
public class VcsTestUtil {
public static VirtualFile createFile(@NotNull Project project, @NotNull final VirtualFile parent, @NotNull final String name,
@Nullable final String content) {
return new WriteCommandAction<VirtualFile>(project) {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
VirtualFile file = parent.createChildData(this, name);
if (content != null) {
file.setBinaryContent(CharsetToolkit.getUtf8Bytes(content));
}
result.setResult(file);
}
}.execute().throwException().getResultObject();
}
/**
* Creates directory inside a write action and returns the resulting reference to it.
* If the directory already exists, does nothing.
*
* @param parent Parent directory.
* @param name Name of the directory.
* @return reference to the created or already existing directory.
*/
public static VirtualFile createDir(@NotNull final Project project, @NotNull final VirtualFile parent, @NotNull final String name) {
return new WriteCommandAction<VirtualFile>(project) {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
VirtualFile dir = parent.findChild(name);
if (dir == null) {
dir = parent.createChildDirectory(this, name);
}
result.setResult(dir);
}
}.execute().throwException().getResultObject();
}
public static void renameFileInCommand(@NotNull Project project, @NotNull final VirtualFile file, @NotNull final String newName) {
new WriteCommandAction.Simple(project) {
@Override
protected void run() throws Throwable {
try {
file.rename(this, newName);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}.execute().throwException();
}
public static void deleteFileInCommand(@NotNull Project project, @NotNull final VirtualFile file) {
new WriteCommandAction.Simple(project) {
@Override
protected void run() throws Throwable {
try {
file.delete(this);
}
catch(IOException ex) {
throw new RuntimeException(ex);
}
}
}.execute();
}
public static void editFileInCommand(@NotNull Project project, @NotNull final VirtualFile file, @NotNull final String newContent) {
assertTrue(file.isValid());
file.getTimeStamp();
new WriteCommandAction.Simple(project) {
@Override
protected void run() throws Throwable {
try {
final long newTs = Math.max(System.currentTimeMillis(), file.getTimeStamp() + 1100);
file.setBinaryContent(newContent.getBytes(), -1, newTs);
final File file1 = new File(file.getPath());
FileUtil.writeToFile(file1, newContent.getBytes());
file.refresh(false, false);
assertTrue(file1 + " / " + newTs, file1.setLastModified(newTs));
}
catch(IOException ex) {
throw new RuntimeException(ex);
}
}
}.execute();
}
public static VirtualFile copyFileInCommand(@NotNull Project project, @NotNull final VirtualFile file,
@NotNull final VirtualFile newParent, @NotNull final String newName) {
return new WriteCommandAction<VirtualFile>(project) {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
try {
result.setResult(file.copy(this, newParent, newName));
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}.execute().getResultObject();
}
public static void moveFileInCommand(@NotNull Project project, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent) {
new WriteCommandAction.Simple(project) {
@Override
protected void run() throws Throwable {
try {
file.move(this, newParent);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}.execute();
}
public static <T> void assertEqualCollections(@NotNull String message, @NotNull Collection<T> actual, @NotNull Collection<T> expected) {
if (!StringUtil.isEmptyOrSpaces(message) && !message.endsWith(":") && !message.endsWith(": ")) {
message += ": ";
}
if (actual.size() != expected.size()) {
fail(message + "Collections don't have the same size. " + stringifyActualExpected(actual, expected));
}
for (T act : actual) {
if (!expected.contains(act)) {
fail(message + "Unexpected object " + act + stringifyActualExpected(actual, expected));
}
}
// backwards is needed for collections which may contain duplicates, e.g. Lists.
for (T exp : expected) {
if (!actual.contains(exp)) {
fail(message + "Object " + exp + " not found in actual collection." + stringifyActualExpected(actual, expected));
}
}
}
public static <T> void assertEqualCollections(@NotNull Collection<T> actual, @NotNull Collection<T> expected) {
assertEqualCollections("", actual, expected);
}
/**
* Testng compares by iterating over 2 collections, but it won't work for sets which may have different order.
*/
public static <T, E> void assertEqualCollections(@NotNull Collection<? extends T> actual,
@NotNull Collection<? extends E> expected,
@NotNull EqualityChecker<T, E> equalityChecker) {
if (actual.size() != expected.size()) {
fail("Collections don't have the same size. " + stringifyActualExpected(actual, expected));
}
for (T act : actual) {
if (!contains2(expected, act, equalityChecker)) {
fail("Unexpected object " + act + stringifyActualExpected(actual, expected));
}
}
// backwards is needed for collections which may contain duplicates, e.g. Lists.
for (E exp : expected) {
if (!contains(actual, exp, equalityChecker)) {
fail("Object " + exp + " not found in actual collection." + stringifyActualExpected(actual, expected));
}
}
}
private static <T, E> boolean contains(@NotNull Collection<? extends T> collection,
@NotNull E object,
@NotNull EqualityChecker<T, E> equalityChecker) {
for (T t : collection) {
if (equalityChecker.areEqual(t, object)) {
return true;
}
}
return false;
}
private static <T, E> boolean contains2(@NotNull Collection<? extends E> collection,
@NotNull T object,
@NotNull EqualityChecker<T, E> equalityChecker) {
for (E e : collection) {
if (equalityChecker.areEqual(object, e)) {
return true;
}
}
return false;
}
public interface EqualityChecker<T, E> {
boolean areEqual(T actual, E expected);
}
@NotNull
public static String stringifyActualExpected(@NotNull Object actual, @NotNull Object expected) {
return "\nExpected:\n" + expected + "\nActual:\n" + actual;
}
@NotNull
public static String toAbsolute(@NotNull String relPath, @NotNull Project project) {
new File(toAbsolute(Collections.singletonList(relPath), project).get(0)).mkdir();
return toAbsolute(Collections.singletonList(relPath), project).get(0);
}
@NotNull
public static List<String> toAbsolute(@NotNull Collection<String> relPaths, @NotNull final Project project) {
return ContainerUtil.map2List(relPaths, new Function<String, String>() {
@Override
public String fun(String s) {
try {
return FileUtil.toSystemIndependentName((new File(project.getBasePath() + "/" + s).getCanonicalPath()));
}
catch (IOException e) {
e.printStackTrace();
return "";
}
}
});
}
public static void assertNotificationShown(@NotNull Project project, @Nullable Notification expected) {
if (expected != null) {
Notification actualNotification =
((TestVcsNotifier)VcsNotifier.getInstance(project)).getLastNotification();
assertNotNull("No notification was shown", actualNotification);
assertEquals("Notification has wrong title", expected.getTitle(), actualNotification.getTitle());
assertEquals("Notification has wrong type", expected.getType(), actualNotification.getType());
assertEquals("Notification has wrong content", adjustTestContent(expected.getContent()), actualNotification.getContent());
}
}
// we allow more spaces and line breaks in tests to make them more readable.
// After all, notifications display html, so all line breaks and extra spaces are ignored.
private static String adjustTestContent(@NotNull String s) {
StringBuilder res = new StringBuilder();
String[] splits = s.split("\n");
for (String split : splits) {
res.append(split.trim());
}
return res.toString();
}
}