PositionManager test framework

This commit is contained in:
Alexander Udalov
2012-08-17 18:15:54 +04:00
parent f6b741674b
commit 8ddeddc895
3 changed files with 763 additions and 0 deletions
@@ -0,0 +1,264 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.debugger;
import com.sun.jdi.*;
import java.util.List;
import java.util.Map;
/**
* @author udalov
*/
public class MockReferenceType implements ReferenceType {
private final String name;
public MockReferenceType(String name) {
this.name = name;
}
@Override
public String name() {
return name;
}
@Override
public String signature() {
throw new UnsupportedOperationException();
}
@Override
public String genericSignature() {
throw new UnsupportedOperationException();
}
@Override
public ClassLoaderReference classLoader() {
throw new UnsupportedOperationException();
}
@Override
public String sourceName() throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public List<String> sourceNames(String s) throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public List<String> sourcePaths(String s) throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public String sourceDebugExtension() throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public boolean isStatic() {
throw new UnsupportedOperationException();
}
@Override
public boolean isAbstract() {
throw new UnsupportedOperationException();
}
@Override
public boolean isFinal() {
throw new UnsupportedOperationException();
}
@Override
public boolean isPrepared() {
throw new UnsupportedOperationException();
}
@Override
public boolean isVerified() {
throw new UnsupportedOperationException();
}
@Override
public boolean isInitialized() {
throw new UnsupportedOperationException();
}
@Override
public boolean failedToInitialize() {
throw new UnsupportedOperationException();
}
@Override
public List<Field> fields() {
throw new UnsupportedOperationException();
}
@Override
public List<Field> visibleFields() {
throw new UnsupportedOperationException();
}
@Override
public List<Field> allFields() {
throw new UnsupportedOperationException();
}
@Override
public Field fieldByName(String s) {
throw new UnsupportedOperationException();
}
@Override
public List<Method> methods() {
throw new UnsupportedOperationException();
}
@Override
public List<Method> visibleMethods() {
throw new UnsupportedOperationException();
}
@Override
public List<Method> allMethods() {
throw new UnsupportedOperationException();
}
@Override
public List<Method> methodsByName(String s) {
throw new UnsupportedOperationException();
}
@Override
public List<Method> methodsByName(String s, String s1) {
throw new UnsupportedOperationException();
}
@Override
public List<ReferenceType> nestedTypes() {
throw new UnsupportedOperationException();
}
@Override
public Value getValue(Field field) {
throw new UnsupportedOperationException();
}
@Override
public Map<Field, Value> getValues(List<? extends Field> fields) {
throw new UnsupportedOperationException();
}
@Override
public ClassObjectReference classObject() {
throw new UnsupportedOperationException();
}
@Override
public List<Location> allLineLocations() throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public List<Location> allLineLocations(String s, String s1) throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public List<Location> locationsOfLine(int i) throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public List<Location> locationsOfLine(String s, String s1, int i) throws AbsentInformationException {
throw new UnsupportedOperationException();
}
@Override
public List<String> availableStrata() {
throw new UnsupportedOperationException();
}
@Override
public String defaultStratum() {
throw new UnsupportedOperationException();
}
@Override
public List<ObjectReference> instances(long l) {
throw new UnsupportedOperationException();
}
@Override
public int majorVersion() {
throw new UnsupportedOperationException();
}
@Override
public int minorVersion() {
throw new UnsupportedOperationException();
}
@Override
public int constantPoolCount() {
throw new UnsupportedOperationException();
}
@Override
public byte[] constantPool() {
throw new UnsupportedOperationException();
}
@Override
public int modifiers() {
throw new UnsupportedOperationException();
}
@Override
public boolean isPrivate() {
throw new UnsupportedOperationException();
}
@Override
public boolean isPackagePrivate() {
throw new UnsupportedOperationException();
}
@Override
public boolean isProtected() {
throw new UnsupportedOperationException();
}
@Override
public boolean isPublic() {
throw new UnsupportedOperationException();
}
@Override
public int compareTo(ReferenceType o) {
throw new UnsupportedOperationException();
}
@Override
public VirtualMachine virtualMachine() {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,296 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.debugger;
import com.sun.jdi.*;
import com.sun.jdi.event.EventQueue;
import com.sun.jdi.request.EventRequestManager;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author udalov
*/
public class MockVirtualMachine implements VirtualMachine {
@Override
public List<ThreadGroupReference> topLevelThreadGroups() {
return Collections.emptyList();
}
@Override
public String version() {
return "1.6";
}
@Override
public List<ReferenceType> classesByName(String s) {
throw new UnsupportedOperationException();
}
@Override
public List<ReferenceType> allClasses() {
throw new UnsupportedOperationException();
}
@Override
public void redefineClasses(Map<? extends ReferenceType, byte[]> map) {
throw new UnsupportedOperationException();
}
@Override
public List<ThreadReference> allThreads() {
return Collections.emptyList();
}
@Override
public void suspend() {
throw new UnsupportedOperationException();
}
@Override
public void resume() {
throw new UnsupportedOperationException();
}
@Override
public EventQueue eventQueue() {
throw new UnsupportedOperationException();
}
@Override
public EventRequestManager eventRequestManager() {
throw new UnsupportedOperationException();
}
@Override
public BooleanValue mirrorOf(boolean b) {
throw new UnsupportedOperationException();
}
@Override
public ByteValue mirrorOf(byte b) {
throw new UnsupportedOperationException();
}
@Override
public CharValue mirrorOf(char c) {
throw new UnsupportedOperationException();
}
@Override
public ShortValue mirrorOf(short i) {
throw new UnsupportedOperationException();
}
@Override
public IntegerValue mirrorOf(int i) {
throw new UnsupportedOperationException();
}
@Override
public LongValue mirrorOf(long l) {
throw new UnsupportedOperationException();
}
@Override
public FloatValue mirrorOf(float v) {
throw new UnsupportedOperationException();
}
@Override
public DoubleValue mirrorOf(double v) {
throw new UnsupportedOperationException();
}
@Override
public StringReference mirrorOf(String s) {
throw new UnsupportedOperationException();
}
@Override
public VoidValue mirrorOfVoid() {
throw new UnsupportedOperationException();
}
@Override
public Process process() {
throw new UnsupportedOperationException();
}
@Override
public void dispose() {
throw new UnsupportedOperationException();
}
@Override
public void exit(int i) {
throw new UnsupportedOperationException();
}
@Override
public void setDefaultStratum(String s) {
throw new UnsupportedOperationException();
}
@Override
public String getDefaultStratum() {
throw new UnsupportedOperationException();
}
@Override
public String description() {
throw new UnsupportedOperationException();
}
@Override
public String name() {
throw new UnsupportedOperationException();
}
@Override
public void setDebugTraceMode(int i) {
throw new UnsupportedOperationException();
}
@Override
public boolean canWatchFieldModification() {
return false;
}
@Override
public boolean canWatchFieldAccess() {
return false;
}
@Override
public boolean canGetBytecodes() {
return false;
}
@Override
public boolean canGetSyntheticAttribute() {
return false;
}
@Override
public boolean canGetOwnedMonitorInfo() {
return false;
}
@Override
public boolean canGetCurrentContendedMonitor() {
return false;
}
@Override
public boolean canGetMonitorInfo() {
return false;
}
@Override
public boolean canUseInstanceFilters() {
return false;
}
@Override
public boolean canRedefineClasses() {
return false;
}
@Override
public boolean canAddMethod() {
return false;
}
@Override
public boolean canUnrestrictedlyRedefineClasses() {
return false;
}
@Override
public boolean canPopFrames() {
return false;
}
@Override
public boolean canGetSourceDebugExtension() {
return false;
}
@Override
public boolean canRequestVMDeathEvent() {
return false;
}
@Override
public boolean canGetMethodReturnValues() {
return false;
}
@Override
public boolean canGetInstanceInfo() {
return false;
}
@Override
public boolean canUseSourceNameFilters() {
return false;
}
@Override
public boolean canForceEarlyReturn() {
return false;
}
@Override
public boolean canBeModified() {
return false;
}
@Override
public boolean canRequestMonitorEvents() {
return false;
}
@Override
public boolean canGetMonitorFrameInfo() {
return false;
}
@Override
public boolean canGetClassFileVersion() {
return false;
}
@Override
public boolean canGetConstantPool() {
return false;
}
@Override
public long[] instanceCounts(List<? extends ReferenceType> types) {
return new long[0];
}
@Override
public VirtualMachine virtualMachine() {
return this;
}
}
@@ -0,0 +1,203 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.debugger;
import com.google.common.collect.Maps;
import com.intellij.debugger.NoDataException;
import com.intellij.debugger.PositionManager;
import com.intellij.debugger.PositionManagerFactory;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.DebugProcess;
import com.intellij.debugger.engine.DebugProcessEvents;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.PlatformTestCase;
import com.sun.jdi.*;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationUtils;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.utils.ExceptionUtils;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author udalov
*/
public abstract class PositionManagerTestCase extends PlatformTestCase {
// Breakpoint is given as a line comment on a specific line, containing the name of the class, where that line can be found.
// This pattern matches against these line comments and saves the class name in the first group
private static final Pattern breakpointPattern = Pattern.compile("^.*//\\s*([a-zA-Z0-9._/$]*)\\s*$");
protected abstract String getTestDataPath();
protected abstract PositionManagerFactory getPositionManagerFactory();
@Override
protected final void setUp() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
try {
PositionManagerTestCase.super.setUp();
}
catch (Exception e) {
ExceptionUtils.rethrow(e);
}
}
});
}
@Override
protected final void tearDown() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
try {
PositionManagerTestCase.super.tearDown();
}
catch (Exception e) {
ExceptionUtils.rethrow(e);
}
}
});
}
@Override
protected void runBareRunnable(Runnable runnable) {
runnable.run();
}
protected void doTest() {
File file = new File(getTestDataPath(), getTestName(true) + ".kt");
String fileContent;
try {
fileContent = FileUtil.loadFile(file);
}
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
final PsiFile psiFile = JetTestUtils.createFile(file.getAbsolutePath(), fileContent, getProject());
final Map<Integer, String> breakpoints = extractBreakpointsInfo(fileContent);
Map<String, ReferenceType> referencesByName = compileFileGetReferenceMap((JetFile) psiFile);
final DebugProcess debugProcess = createDebugProcess(referencesByName);
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
try {
PositionManager positionManager = getPositionManagerFactory().createPositionManager(debugProcess);
assertNotNull(positionManager);
for (Integer lineNumber : breakpoints.keySet()) {
String className = breakpoints.get(lineNumber);
SourcePosition position = SourcePosition.createFromLine(psiFile, lineNumber);
assertPositionIsValid(position, className, positionManager);
}
}
catch (NoDataException e) {
ExceptionUtils.rethrow(e);
}
}
});
}
private static Map<Integer, String> extractBreakpointsInfo(String fileContent) {
Map<Integer, String> breakpoints = Maps.newHashMap();
String[] lines = StringUtil.convertLineSeparators(fileContent).split("\n");
for (int i = 0; i < lines.length; i++) {
Matcher matcher = breakpointPattern.matcher(lines[i]);
if (matcher.matches()) {
// Line breakpoint numbers are 1-based
breakpoints.put(i + 1, matcher.group(1));
}
}
return breakpoints;
}
private static Map<String, ReferenceType> compileFileGetReferenceMap(JetFile jetFile) {
ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(jetFile);
Map<String, ReferenceType> referencesByName = Maps.newHashMap();
for (String classFileName : classFileFactory.files()) {
String name = classFileName.substring(0, classFileName.lastIndexOf('.'));
referencesByName.put(name, new MockReferenceType(name));
}
return referencesByName;
}
private DebugProcessEvents createDebugProcess(final Map<String, ReferenceType> referencesByName) {
DebugProcessEvents events = new DebugProcessEvents(getProject()) {
private VirtualMachineProxyImpl virtualMachineProxy;
@Override
public VirtualMachineProxyImpl getVirtualMachineProxy() {
if (virtualMachineProxy == null) {
virtualMachineProxy = new MockVirtualMachineProxy(this, referencesByName);
}
return virtualMachineProxy;
}
};
return events;
}
private static void assertPositionIsValid(SourcePosition position, String className, PositionManager positionManager) throws NoDataException {
List<ReferenceType> classes = positionManager.getAllClasses(position);
assertNotNull(classes);
assertEquals(1, classes.size());
ReferenceType type = classes.get(0);
assertEquals(className, type.name());
}
private static class MockVirtualMachineProxy extends VirtualMachineProxyImpl {
private final Map<String, ReferenceType> referencesByName;
private MockVirtualMachineProxy(DebugProcessEvents debugProcess, Map<String, ReferenceType> referencesByName) {
super(debugProcess, new MockVirtualMachine());
this.referencesByName = referencesByName;
}
@Override
public List<ReferenceType> allClasses() {
return new ArrayList<ReferenceType>(referencesByName.values());
}
@Override
public List<ReferenceType> classesByName(String name) {
ReferenceType ref = referencesByName.get(name);
if (ref == null) {
return Collections.emptyList();
}
else {
return Collections.singletonList(ref);
}
}
}
}