mad testing: don't shrink offsets to speed up minimization

This commit is contained in:
peter
2018-02-13 21:10:32 +01:00
parent eac5448e1c
commit 484c9e29b9
9 changed files with 25 additions and 14 deletions
@@ -73,7 +73,9 @@ public class Generator<T> {
/**
* Turns off automatic minimization for the data produced by this generator (and its components, if any).
* This can be useful to speed up minimization by not wasting time on shrinking objects where it makes no sense.
* This can be useful to speed up minimization by not wasting time on shrinking objects where it makes no sense.
* It's especially useful when using stateful generators (e.g. {@link ImperativeCommand}), because
* shrinkable values there can lead to doubling of the shrinking time.
*/
public Generator<T> noShrink() {
return from(data -> data.generateNonShrinkable(this));
@@ -82,7 +82,10 @@ public interface ImperativeCommand {
* The message is a Java format string, so you can use it to include the generated value, e.g.
* {@code String s = generateValue(stringsOf(asciiLetters(), "Generated %s")}.<p/>
* If you don't want to generate message, or would like to show the generated value in a custom way, pass {@code null}.
* You can use {@link #logMessage} later to still leave a trace of this value generation in the log.
* You can use {@link #logMessage} later to still leave a trace of this value generation in the log.<p/>
*
* Consider making generators non-shrinkable (by invoking {@link Generator#noShrink()}) where possible
* because it can speed up overall failing scenario minimization significantly.
*/
<T> T generateValue(@NotNull Generator<T> generator, @Nullable String logMessage);
@@ -29,6 +29,7 @@ import com.intellij.psi.SmartPsiFileRange;
import com.intellij.psi.impl.DebugUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jetCheck.Generator;
/**
* @author peter
@@ -98,4 +99,14 @@ abstract class ActionOnRange implements MadTestingAction {
}
return myFinalRange;
}
@SuppressWarnings("SameParameterValue")
protected int generatePsiOffset(@NotNull Environment env, @Nullable String logMessage) {
return env.generateValue(Generator.integers(0, getFile().getTextLength()).noShrink(), logMessage);
}
protected int generateDocOffset(@NotNull Environment env, @Nullable String logMessage) {
return env.generateValue(Generator.integers(0, getDocument().getTextLength()).noShrink(), logMessage);
}
}
@@ -36,9 +36,8 @@ public class DeleteRange extends ActionOnRange {
public void performCommand(@NotNull Environment env) {
PsiFile psiFile = getFile();
int fileLength = psiFile.getTextLength();
int startOffset = env.generateValue(Generator.integers(0, fileLength), null);
int endOffset = Math.min(fileLength, startOffset + env.generateValue(Generator.integers(IntDistribution.geometric(10)), null));
int startOffset = generatePsiOffset(env, null);
int endOffset = Math.min(psiFile.getTextLength(), startOffset + env.generateValue(Generator.integers(IntDistribution.geometric(10)).noShrink(), null));
PsiElement start = psiFile.findElementAt(startOffset);
PsiElement end = psiFile.findElementAt(endOffset);
if (start == null || end == null) return;
@@ -25,7 +25,7 @@ public class InsertLineComment extends ActionOnRange {
public void performCommand(@NotNull Environment env) {
PsiDocumentManager.getInstance(getProject()).commitDocument(getDocument());
int randomOffset = env.generateValue(Generator.integers(0, getFile().getTextLength()), null);
int randomOffset = generatePsiOffset(env, null);
PsiElement leaf = getFile().findElementAt(randomOffset);
TextRange leafRange = leaf != null ? leaf.getTextRange() : null;
int insertOffset = leafRange != null ? leafRange.getEndOffset() : 0;
@@ -30,7 +30,7 @@ public class InsertString extends ActionOnRange {
@Override
public void performCommand(@NotNull Environment env) {
int offset = env.generateValue(Generator.integers(0, getDocument().getTextLength()), null);
int offset = generateDocOffset(env, null);
String toInsert = env.generateValue(Generator.stringsOf(Generator.asciiPrintableChars()), "Insert '%s' at " + offset + " in " + getPath());
WriteCommandAction.runWriteCommandAction(getProject(), () -> getDocument().insertString(offset, toInsert));
}
@@ -82,8 +82,7 @@ public class InvokeCompletion extends ActionOnRange {
@Override
public void performCommand(@NotNull Environment env) {
int offset = env.generateValue(Generator.integers(0, getDocument().getTextLength()),
"Invoke basic completion at offset %s (" + getPath() + ")");
int offset = generateDocOffset(env, "Invoke basic completion at offset %s (" + getPath() + ")");
String selectionCharacters = myPolicy.getPossibleSelectionCharacters();
char c = selectionCharacters.charAt(env.generateValue(Generator.integers(0, selectionCharacters.length() - 1), null));
performActionAt(offset, c, items -> env.generateValue(Generator.sampledFrom(items), null), env::logMessage);
@@ -74,8 +74,7 @@ public class InvokeIntention extends ActionOnRange {
@Override
public void performCommand(@NotNull Environment env) {
int offset = env.generateValue(Generator.integers(0, getDocument().getTextLength()),
"Go to offset %s and run daemon (" + getPath() + ")");
int offset = generateDocOffset(env, "Go to offset %s and run daemon (" + getPath() + ")");
doInvokeIntention(offset, actions -> {
if (actions.isEmpty()) {
@@ -83,7 +82,7 @@ public class InvokeIntention extends ActionOnRange {
return null;
}
IntentionAction result = env.generateValue(Generator.sampledFrom(actions), null);
IntentionAction result = env.generateValue(Generator.sampledFrom(actions).noShrink(), null);
env.logMessage("Invoke intention '" + result.getText() + "'");
return result;
});
@@ -41,7 +41,6 @@ import com.intellij.testFramework.RunAll;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.JBIterable;
import com.intellij.util.containers.TreeTraversal;
import com.intellij.util.ui.UIUtil;
@@ -236,7 +235,6 @@ public class MadTestingUtil {
return () -> env -> new RunAll()
.append(() -> {
File ioFile = env.generateValue(randomFiles, "Working with %s");
System.out.println(ioFile);
VirtualFile vFile = copyFileToProject(ioFile, fixture, rootPath);
PsiFile psiFile = fixture.getPsiManager().findFile(vFile);
if (psiFile instanceof PsiBinaryFile || psiFile instanceof PsiPlainTextFile) {