/**
* Copyright 2011 Intuit Inc. All Rights Reserved
*/
package com.intuit.tank.tools.debugger;
/*
* #%L
* Intuit Tank Agent Debugger
* %%
* Copyright (C) 2011 - 2015 Intuit Inc.
* %%
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* #L%
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.xml.bind.JAXBException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SquiggleUnderlineHighlightPainter;
import org.fife.ui.rtextarea.GutterIconInfo;
import org.fife.ui.rtextarea.RTextScrollPane;
import com.intuit.tank.api.model.v1.datafile.DataFileDescriptor;
import com.intuit.tank.api.model.v1.project.KeyPair;
import com.intuit.tank.api.model.v1.project.ProjectTO;
import com.intuit.tank.client.v1.datafile.DataFileClient;
import com.intuit.tank.harness.APITestHarness;
import com.intuit.tank.harness.TestPlanSingleton;
import com.intuit.tank.harness.data.HDScript;
import com.intuit.tank.harness.data.HDScriptGroup;
import com.intuit.tank.harness.data.HDScriptUseCase;
import com.intuit.tank.harness.data.HDTestPlan;
import com.intuit.tank.harness.data.HDTestVariables;
import com.intuit.tank.harness.data.HDVariable;
import com.intuit.tank.harness.data.HDWorkload;
import com.intuit.tank.harness.data.Header;
import com.intuit.tank.harness.data.RequestStep;
import com.intuit.tank.harness.data.TestStep;
import com.intuit.tank.harness.functions.JexlIOFunctions;
import com.intuit.tank.harness.functions.JexlStringFunctions;
import com.intuit.tank.harness.logging.LogUtil;
import com.intuit.tank.logging.LogEventType;
import com.intuit.tank.logging.LoggingProfile;
import com.intuit.tank.runner.TestStepContext;
import com.intuit.tank.tools.debugger.ActionProducer.IconSize;
import com.intuit.tank.vm.api.enumerated.WatsAgentCommand;
import com.intuit.tank.vm.common.TankConstants;
/**
* ScrioptFilterRunner
*
* @author dangleton
*
*/
public class AgentDebuggerFrame extends JFrame {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LogManager.getLogger(AgentDebuggerFrame.class);
private RSyntaxTextArea scriptEditorTA;
private RTextScrollPane scriptEditorScrollPane;
private boolean standalone;
private ActionProducer debuggerActions;
private HDWorkload currentWorkload;
private HDTestPlan currentTestPlan;
private JComboBox<HDTestPlan> testPlanChooser;
private JComboBox<TankClientChoice> tankClientChooser;
private List<StepListener> stepChangedListeners = new ArrayList<StepListener>();
private List<ScriptChangedListener> scriptChangedListeners = new ArrayList<ScriptChangedListener>();
private Map<String, String> projectVariables = new HashMap<String, String>();
private List<Integer> datafileList = new ArrayList<Integer>();
private List<DebugStep> steps = new ArrayList<DebugStep>();
private int currentRunningStep;
private ActionComponents actionComponents;
private DebuggerFlowController flowController;
private APITestHarness harness;
private File workingDir;
private Thread runningThread;
private RSyntaxTextArea loggerTA;
private InfiniteProgressPanel glassPane;
private Icon errorIcon;
private Icon modifiedIcon;
private Icon skippedIcon;
private RequestResponsePanel requestResponsePanel;
private ScriptSource scriptSource;
private int lastLine;
private int multiSelectStart;
private int multiSelectEnd;
private boolean multiSelect;
/**
* @throws HeadlessException
*/
public AgentDebuggerFrame(final boolean isStandalone, String serviceUrl) throws HeadlessException {
super("Intuit Tank Agent Debugger");
workingDir = PanelBuilder.createWorkingDir(this, serviceUrl);
setSize(new Dimension(1024, 800));
setBounds(new Rectangle(getSize()));
setPreferredSize(getSize());
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
this.standalone = isStandalone;
addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
quit();
}
});
errorIcon = ActionProducer.getIcon("bullet_error.png", IconSize.SMALL);
modifiedIcon = ActionProducer.getIcon("bullet_code_change.png", IconSize.SMALL);
skippedIcon = ActionProducer.getIcon("skip.png", IconSize.SMALL);
this.glassPane = new InfiniteProgressPanel();
setGlassPane(glassPane);
debuggerActions = new ActionProducer(this, serviceUrl);
requestResponsePanel = new RequestResponsePanel(this);
requestResponsePanel.init();
testPlanChooser = new JComboBox();
testPlanChooser.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent event) {
if (event.getItem() != null) {
HDTestPlan selected = (HDTestPlan) event.getItem();
if (!selected.equals(currentTestPlan)) {
setCurrentTestPlan(selected);
}
}
}
});
tankClientChooser = new JComboBox<TankClientChoice>();
debuggerActions.setChoiceComboBoxOptions(tankClientChooser);
actionComponents = new ActionComponents(standalone, testPlanChooser, tankClientChooser, debuggerActions);
addScriptChangedListener(actionComponents);
setJMenuBar(actionComponents.getMenuBar());
Component topPanel = PanelBuilder.createTopPanel(actionComponents);
Component bottomPanel = PanelBuilder.createBottomPanel(this);
Component contentPanel = PanelBuilder.createContentPanel(this);
final JPopupMenu popup = actionComponents.getPopupMenu();
scriptEditorTA.setPopupMenu(null);
scriptEditorTA.addMouseListener(new MouseAdapter() {
int lastHash;
@Override
public void mousePressed(MouseEvent e) {
maybeShow(e);
}
@Override
public void mouseReleased(MouseEvent e) {
maybeShow(e);
}
private void maybeShow(MouseEvent e) {
if (lastHash == getHash(e)) {
return;
}
if (e.isPopupTrigger()) {
// select the line
try {
int offset = scriptEditorTA.viewToModel(e.getPoint());
Rectangle modelToView = scriptEditorTA.modelToView(offset);
Point point = new Point(modelToView.x + 1, e.getPoint().y);
if (modelToView.contains(point)) {
if (!multiSelect) {
int line = scriptEditorTA.getLineOfOffset(offset);
scriptEditorTA.setCurrentLine(line);
}
popup.show(e.getComponent(), e.getX(), e.getY());
}
} catch (BadLocationException e1) {
e1.printStackTrace();
}
} else if (e.isShiftDown()) {
int line = scriptEditorTA.getCaretLineNumber();
int start = Math.min(line, lastLine);
int end = Math.max(line, lastLine);
multiSelect = end - start > 1;
if (multiSelect) {
multiSelectStart = start;
multiSelectEnd = end;
try {
scriptEditorTA.setEnabled(true);
scriptEditorTA.select(scriptEditorTA.getLineStartOffset(start), scriptEditorTA.getLineEndOffset(end));
scriptEditorTA.setEnabled(false);
} catch (BadLocationException e1) {
e1.printStackTrace();
multiSelect = false;
}
}
} else {
multiSelect = false;
lastLine = scriptEditorTA.getCaretLineNumber();
}
lastHash = getHash(e);
}
private int getHash(MouseEvent e) {
return new HashCodeBuilder().append(e.getButton()).append(e.getSource().hashCode()).append(e.getPoint()).toHashCode();
}
});
JSplitPane mainSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
mainSplit.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
mainSplit.setTopComponent(contentPanel);
mainSplit.setBottomComponent(bottomPanel);
mainSplit.setDividerLocation(600);
mainSplit.setResizeWeight(0.8D);
mainSplit.setDividerSize(5);
add(topPanel, BorderLayout.NORTH);
add(mainSplit, BorderLayout.CENTER);
WindowUtil.centerOnScreen(this);
pack();
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
handleKeyEvent(e);
}
return false;
}
});
}
public ActionProducer getDebuggerActions() {
return debuggerActions;
}
/**
* @return the tankClientChooser
*/
public JComboBox<TankClientChoice> getTankClientChooser() {
return tankClientChooser;
}
private void handleKeyEvent(KeyEvent event) {
if (!(event.getSource() instanceof JComboBox)) {
if (event.getKeyCode() == KeyEvent.VK_UP) {
moveCursor(true);
} else if (event.getKeyCode() == KeyEvent.VK_DOWN) {
moveCursor(false);
}
}
}
protected void moveCursor(boolean moveUp) {
try {
scriptEditorTA.grabFocus();
int caretLineNumber = this.scriptEditorTA.getCaretLineNumber() + (moveUp ? -1 : 1);
if (caretLineNumber > 0 && moveUp) {
scriptEditorTA.setCurrentLine(caretLineNumber);
fireStepChanged(caretLineNumber);
}
int lastLine = scriptEditorTA.getLineOfOffset(this.scriptEditorTA.getText().length());
if (!moveUp && caretLineNumber <= lastLine) {
scriptEditorTA.setCurrentLine(caretLineNumber);
fireStepChanged(caretLineNumber);
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
/**
* @return the scriptSource
*/
public ScriptSource getScriptSource() {
return scriptSource;
}
/**
* @param scriptSource
* the scriptSource to set
*/
public void setScriptSource(ScriptSource scriptSource) {
this.scriptSource = scriptSource;
debuggerActions.getReloadAction().setEnabled(scriptSource != null);
}
public void startWaiting() {
glassPane.start();
}
public void stopWaiting() {
glassPane.stop();
}
public void addStepChangedListener(StepListener l) {
stepChangedListeners.add(l);
}
public void addScriptChangedListener(ScriptChangedListener l) {
scriptChangedListeners.add(l);
}
public boolean runTimingSteps() {
return actionComponents.getRunTimingStepsCB().isSelected();
}
/**
* @return the scriptEditorTA
*/
public RSyntaxTextArea getScriptEditorTA() {
return scriptEditorTA;
}
/**
* @param scriptEditorTA
* the scriptEditorTA to set
*/
public void setScriptEditorTA(RSyntaxTextArea scriptEditorTA) {
this.scriptEditorTA = scriptEditorTA;
}
/**
* @return the scriptEditorScrollPane
*/
public RTextScrollPane getScriptEditorScrollPane() {
return scriptEditorScrollPane;
}
/**
* @param scriptEditorScrollPane
* the scriptEditorScrollPane to set
*/
public void setScriptEditorScrollPane(RTextScrollPane scriptEditorScrollPane) {
this.scriptEditorScrollPane = scriptEditorScrollPane;
}
/**
* @return the steps
*/
public List<DebugStep> getSteps() {
return steps;
}
/**
* @return the loggerTA
*/
public RSyntaxTextArea getLoggerTA() {
return loggerTA;
}
/**
* @param loggerTA
* the loggerTA to set
*/
public void setLoggerTA(RSyntaxTextArea loggerTA) {
this.loggerTA = loggerTA;
}
/**
* @return the projectVariables
*/
public Map<String, String> getProjectVariables() {
return projectVariables;
}
/**
* @param projectVariables
* the projectVariables to set
*/
public void setProjectVariables(Map<String, String> projectVariables) {
this.projectVariables.clear();
if (projectVariables != null) {
this.projectVariables.putAll(projectVariables);
}
}
/**
* @return the currentWorkload
*/
public HDWorkload getCurrentWorkload() {
return currentWorkload;
}
public void clearBookmarks() {
GutterIconInfo[] bookmarks = this.scriptEditorScrollPane.getGutter().getBookmarks();
for (GutterIconInfo gi : bookmarks) {
try {
int line = this.scriptEditorTA.getLineOfOffset(gi.getMarkedOffset());
this.scriptEditorScrollPane.getGutter().toggleBookmark(line);
} catch (BadLocationException e) {
LOG.error("Error unsetting bookmark: " + e);
}
}
}
public void clearSkips() {
GutterIconInfo[] bookmarks = this.scriptEditorScrollPane.getGutter().getAllTrackingIcons();
for (GutterIconInfo gi : bookmarks) {
this.scriptEditorScrollPane.getGutter().removeTrackingIcon(gi);
if (flowController != null) {
flowController.getSkipList().clear();
}
}
}
public boolean setStepfromString(String stepXML) {
boolean ret = false;
try {
TestStep unmarshalledStep = JaxbUtil.unmarshall(stepXML, TestStep.class);
scriptEditorScrollPane.getGutter().addOffsetTrackingIcon(scriptEditorTA.getLineStartOffset(unmarshalledStep.getStepIndex()), modifiedIcon);
DebugStep debugStep = steps.get(unmarshalledStep.getStepIndex());
debugStep.setStepRun(unmarshalledStep);
if (currentTestPlan != null) {
for (HDScriptGroup group : currentTestPlan.getGroup()) {
for (HDScript script : group.getGroupSteps()) {
for (HDScriptUseCase useCase : script.getUseCase()) {
for (int i = useCase.getScriptSteps().size(); --i >= 0;) {
TestStep step = useCase.getScriptSteps().get(i);
if (step.getStepIndex() == unmarshalledStep.getStepIndex()) {
useCase.getScriptSteps().remove(i);
updateStepLabel(unmarshalledStep);
useCase.getScriptSteps().add(i, unmarshalledStep);
}
}
}
}
}
int pos = scriptEditorTA.getCaretPosition();
buildEditorString(currentTestPlan);
scriptEditorTA.setCaretPosition(pos);
}
ret = true;
} catch (Exception e) {
showError("Error unmarshalling step: " + e);
}
return ret;
}
private void updateStepLabel(TestStep testStep) {
if (testStep instanceof RequestStep) {
StringBuilder label = new StringBuilder();
RequestStep step = (RequestStep) testStep;
label.append(step.getRequest().getProtocol()).append("://").append(step.getRequest().getHost()).append(step.getRequest().getPath());
int qsCount = 0;
if (step.getRequest().getQueryString() != null) {
for (Header qs : step.getRequest().getQueryString()) {
label.append(qsCount == 0 ? "?" : "&");
label.append(qs.getKey()).append("=").append(qs.getValue());
qsCount++;
}
}
step.getRequest().setLabel(StringUtils.abbreviate(label.toString(), 1024));
}
return;
}
public void showError(String msg) {
LOG.error("Error: " + msg);
stopWaiting();
JOptionPane.showMessageDialog(this, msg, "Error", JOptionPane.ERROR_MESSAGE);
}
/**
* Quits the app and attempts to delete the working dir
*/
public void quit() {
super.setVisible(false);
if (workingDir.exists()) {
try {
FileUtils.deleteDirectory(workingDir);
} catch (IOException e) {
System.out.println("Error deleting directory " + workingDir.getAbsolutePath() + ": " + e);
}
}
if (this.standalone) {
System.exit(0);
}
}
/**
* @param currentWorkload
* the currentWorkload to set
*/
public void setCurrentWorkload(HDWorkload currentWorkload) {
setCurrentTestPlan(null);
this.currentWorkload = currentWorkload;
if (currentWorkload != null) {
DefaultComboBoxModel<HDTestPlan> model = new DefaultComboBoxModel<HDTestPlan>(currentWorkload.getPlans().toArray(new HDTestPlan[currentWorkload.getPlans().size()]));
if (currentWorkload.getPlans().size() > 0) {
setCurrentTestPlan(currentWorkload.getPlans().get(0));
model.setSelectedItem(currentTestPlan);
}
testPlanChooser.setModel(model);
} else {
setCurrentTestPlan(null);
testPlanChooser.setModel(new DefaultComboBoxModel<HDTestPlan>());
}
}
/**
* @return the currentTestPlan
*/
public HDTestPlan getCurrentTestPlan() {
return currentTestPlan;
}
public void setCurrentStep(final int stepIndex) {
currentRunningStep = stepIndex;
int stepToSet = Math.max(0, currentRunningStep);
if (currentRunningStep < 0) {
scriptEditorTA.setActiveLineRange(-1, -1);
} else {
scriptEditorTA.setActiveLineRange(currentRunningStep + 1, currentRunningStep + 1);
}
scriptEditorTA.setCurrentLine(stepToSet);
repaint();
if (flowController.isSkipping()) {
actionComponents.skipTo();
} else {
actionComponents.doneSkipping();
}
}
/**
* @return the currentRunningStep
*/
public int getCurrentRunningStep() {
return currentRunningStep;
}
public ActionComponents getActionComponents() {
return actionComponents;
}
/**
* @param currentTestPlan
* the currentTestPlan to set
*/
public void setCurrentTestPlan(HDTestPlan currentTestPlan) {
this.currentTestPlan = currentTestPlan;
steps.clear();
currentRunningStep = -1;
scriptEditorScrollPane.getGutter().removeAllTrackingIcons();
buildEditorString(currentTestPlan);
if (!steps.isEmpty()) {
fireStepChanged(0);
}
scriptEditorTA.setCaretPosition(0);
fireScriptChanged();
}
private void buildEditorString(HDTestPlan currentTestPlan) {
StringBuilder sb = new StringBuilder();
if (currentTestPlan != null) {
for (HDScriptGroup group : currentTestPlan.getGroup()) {
for (HDScript script : group.getGroupSteps()) {
for (HDScriptUseCase useCase : script.getUseCase()) {
for (TestStep step : useCase.getScriptSteps()) {
if (sb.length() != 0) {
sb.append('\n');
}
sb.append(step.getInfo());
steps.add(new DebugStep(step));
}
}
}
}
}
GutterIconInfo[] allTrackingIcons = scriptEditorScrollPane.getGutter().getAllTrackingIcons();
List<IconContainer> icons = new ArrayList<IconContainer>(allTrackingIcons.length);
for (GutterIconInfo gi : allTrackingIcons) {
try {
icons.add(new IconContainer(scriptEditorTA.getLineOfOffset(gi.getMarkedOffset()), gi.getIcon()));
} catch (BadLocationException e) {
e.printStackTrace();
}
}
scriptEditorScrollPane.getGutter().removeAllTrackingIcons();
scriptEditorTA.setText(sb.toString());
for (IconContainer ic : icons) {
try {
scriptEditorScrollPane.getGutter().addOffsetTrackingIcon(scriptEditorTA.getLineStartOffset(ic.getLine()), ic.getIcon());
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
/**
* @return the standalone
*/
public boolean isStandalone() {
return standalone;
}
private String buildScriptString() throws JAXBException {
HDWorkload workload = new HDWorkload();
workload.setName(currentWorkload.getName());
workload.setDescription(currentWorkload.getDescription());
if (currentWorkload.getVariables() != null) {
HDTestVariables variables = new HDTestVariables(currentWorkload.getVariables().isAllowOverride());
for (Entry<String, String> entry : this.projectVariables.entrySet()) {
variables.addVariable(entry.getKey(), entry.getValue());
}
workload.setVariables(variables);
}
workload.getPlans().add(currentTestPlan);
return JaxbUtil.marshall(workload);
}
void fireScriptChanged() {
for (ScriptChangedListener l : scriptChangedListeners) {
l.scriptChanged(currentTestPlan);
}
}
void fireStepChanged(int stepIndex) {
DebugStep step = null;
if (stepIndex >= 0 && stepIndex < steps.size()) {
step = steps.get(stepIndex);
}
for (StepListener l : stepChangedListeners) {
l.stepChanged(step);
}
}
void fireStepStarted(int stepIndex) {
DebugStep step = null;
if (stepIndex >= 0 && stepIndex < steps.size()) {
step = steps.get(stepIndex);
}
for (StepListener l : stepChangedListeners) {
l.stepEntered(step);
}
}
void fireStepExited(int stepIndex) {
DebugStep step = null;
if (stepIndex >= 0 && stepIndex < steps.size()) {
step = steps.get(stepIndex);
}
for (StepListener l : stepChangedListeners) {
l.stepExited(step);
}
}
public void setDataFromProject(ProjectTO selected) {
projectVariables.clear();
datafileList.clear();
for (KeyPair pair : selected.getVariables()) {
projectVariables.put(pair.getKey(), pair.getValue());
}
datafileList.addAll(selected.getDataFileIds());
}
public void next() {
flowController.doNext();
}
public boolean hasBreakPoint(int i) {
try {
GutterIconInfo[] bookmarks = this.scriptEditorScrollPane.getGutter().getBookmarks();
for (GutterIconInfo info : bookmarks) {
int line = this.scriptEditorTA.getLineOfOffset(info.getMarkedOffset());
if (line == i) {
return true;
}
}
} catch (BadLocationException e) {
LOG.warn("Error processing breakpoints: " + e);
}
return false;
}
public void runToBreakpoint() {
flowController.setSkipping(true);
actionComponents.skipTo();
flowController.doNext();
}
public void stop() {
try {
if (harness != null) {
harness.setCommand(WatsAgentCommand.kill);
}
if (runningThread != null) {
runningThread.interrupt();
}
} finally {
testFinished();
runningThread = null;
harness = null;
actionComponents.stop();
}
}
public void start() {
startWaiting();
flowController = new DebuggerFlowController(this);
scriptEditorTA.getHighlighter().removeAllHighlights();
actionComponents.start();
loggerTA.setText("");
loggerTA.setCaretPosition(0);
loggerTA.repaint();
new Thread(new Runnable() {
public void run() {
fireStepChanged(-1);
if (!steps.isEmpty()) {
for (DebugStep step : steps) {
step.clear();
}
setCurrentStep(-1);
for (GutterIconInfo gi : scriptEditorScrollPane.getGutter().getAllTrackingIcons()) {
if (gi.getIcon() == errorIcon) {
scriptEditorScrollPane.getGutter().removeTrackingIcon(gi);
} else if (gi.getIcon() == skippedIcon) {
try {
flowController.skip(scriptEditorTA.getLineOfOffset(gi.getMarkedOffset()));
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
// start apiHarness and get the variables....
try {
createHarness();
runningThread = new Thread(new Runnable() {
public void run() {
harness.runConcurrentTestPlans();
}
});
runningThread.start();
} catch (Exception e) {
showError("Error starting test: " + e);
actionComponents.stop();
}
} else {
stopWaiting();
actionComponents.stop();
}
}
}).start();
}
private void createHarness() throws JAXBException {
APITestHarness.destroyCurrentInstance();
harness = APITestHarness.getInstance();
harness.setFlowControllerTemplate(flowController);
TankClientChoice choice = (TankClientChoice) tankClientChooser.getSelectedItem();
harness.setTankHttpClientClass(choice.getClientClass());
harness.getAgentRunData().setActiveProfile(LoggingProfile.VERBOSE);
harness.getAgentRunData().setInstanceId("DebuggerInstance");
harness.getAgentRunData().setMachineName("debugger");
harness.getAgentRunData().setNumUsers(1);
harness.getAgentRunData().setJobId("debuggerJob");
harness.getAgentRunData().setTotalAgents(1);
harness.setDebug(true);
List<String> testPlansXmls = new ArrayList<String>();
testPlansXmls.add(buildScriptString());
TestPlanSingleton.getInstance().setTestPlans(testPlansXmls);
downloadDataFiles();
JexlIOFunctions.resetStatics();
JexlStringFunctions.resetStatics();
}
private void downloadDataFiles() {
if (!datafileList.isEmpty()) {
DataFileClient client = debuggerActions.getDataFileClient();
for (Integer id : datafileList) {
DataFileDescriptor dataFile = client.getDataFile(id);
if (dataFile != null) {
saveDataFile(client, dataFile, datafileList.size() == 1);
}
}
}
}
private void saveDataFile(DataFileClient client, DataFileDescriptor dataFileDescriptor, boolean isDefault) {
File dataFile = new File(workingDir, dataFileDescriptor.getName());
FileOutputStream fos = null;
InputStream is = null;
try {
LOG.info("writing file " + dataFileDescriptor.getName() + " to " + dataFile.getAbsolutePath());
is = client.getDataFileDataStream(dataFileDescriptor.getId());
fos = new FileOutputStream(dataFile);
IOUtils.copy(is, fos);
IOUtils.closeQuietly(fos);
if (isDefault && !dataFileDescriptor.getName().equals(TankConstants.DEFAULT_CSV_FILE_NAME)) {
File defaultFile = new File(workingDir, TankConstants.DEFAULT_CSV_FILE_NAME);
FileUtils.copyFile(dataFile, defaultFile);
}
} catch (Exception e) {
LOG.error("Error downloading csv file: " + e, e);
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(fos);
}
}
public void setNextStep(TestStepContext context) {
setCurrentStep(context.getTestStep().getStepIndex());
}
public void moveCursor(TestStepContext context) {
int stepIndex = context.getTestStep().getStepIndex();
scriptEditorTA.setActiveLineRange(stepIndex, stepIndex);
}
public void stepStarted(final TestStepContext context) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
actionComponents.stepping();
int stepIndex = context.getTestStep().getStepIndex();
setCurrentStep(stepIndex);
DebugStep debugStep = steps.get(currentRunningStep);
if (debugStep != null) {
debugStep.setEntryVariables(context.getVariables().getVaribleValues());
debugStep.setRequest(context.getRequest());
debugStep.setResponse(context.getResponse());
}
fireStepChanged(stepIndex);
fireStepStarted(stepIndex);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void stepFinished(final TestStepContext context) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
actionComponents.doneStepping();
DebugStep debugStep = steps.get(currentRunningStep);
if (debugStep != null) {
debugStep.setExitVariables(context.getVariables().getVaribleValues());
debugStep.setRequest(context.getRequest());
debugStep.setResponse(context.getResponse());
}
try {
if (context.getResponse() != null && (context.getResponse().getHttpCode() >= 400 || context.getResponse().getHttpCode() == -1)) {
// highlight the line
int lineStartOffset = scriptEditorTA.getLineStartOffset(currentRunningStep);
int lineEndOffset = scriptEditorTA.getLineEndOffset(currentRunningStep);
scriptEditorTA.getHighlighter().addHighlight(lineStartOffset, lineEndOffset, new SquiggleUnderlineHighlightPainter(Color.RED));
}
} catch (BadLocationException e1) {
e1.printStackTrace();
}
if (!context.getErrors().isEmpty()) {
try {
debugStep.setErrors(context.getErrors());
scriptEditorScrollPane.getGutter().addOffsetTrackingIcon(scriptEditorTA.getLineStartOffset(currentRunningStep), errorIcon);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
fireStepExited(context.getTestStep().getStepIndex());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void testStarted() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
stopWaiting();
actionComponents.setRunningActions(true);
}
});
}
public void testFinished() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
runningThread = null;
harness = null;
scriptEditorTA.setActiveLineRange(-1, -1);
actionComponents.stop();
}
});
}
public void setDataFiles(List<DataFileDescriptor> selectedObjects) {
this.datafileList.clear();
for (DataFileDescriptor d : selectedObjects) {
datafileList.add(d.getId());
}
}
public TestStep getStep(int stepIndex) {
return steps.get(stepIndex).getStepRun();
}
public void setCurrentTitle(String string) {
this.actionComponents.setCurrentTitle(string);
}
public void pause() {
flowController.skipTo(-1);
flowController.setSkipping(false);
this.actionComponents.doneSkipping();
}
/**
* @param args
*/
public static void main(String[] args) {
try {
java.security.Security.setProperty("networkaddress.cache.ttl", "0");
} catch (Throwable e1) {
LOG.warn(LogUtil.getLogMessage("Error setting dns timeout: " + e1.toString(), LogEventType.System));
}
try {
System.setProperty("jsse.enableSNIExtension", "false");
} catch (Throwable e1) {
LOG.warn(LogUtil.getLogMessage("Error disabling SNI extension: " + e1.toString(), LogEventType.System));
}
try {
System.setProperty("jdk.certpath.disabledAlgorithms", "");
} catch (Throwable e1) {
System.err.println("Error setting property jdk.certpath.disabledAlgorithms: " + e1.toString());
e1.printStackTrace();
}
String url = "";
if (args.length > 0) {
url = args[0];
}
/* Properties props = new Properties();
try {
InputStream configStream = AgentDebuggerFrame.class.getResourceAsStream("/log4j.properties");
props.load(configStream);
configStream.close();
} catch (IOException e) {
System.out.println("Error: Cannot laod configuration file ");
}
props.setProperty("log4j.appender.agent.File", "debugger.log");
LogManager.resetConfiguration();
PropertyConfigurator.configure(props);
*/
new AgentDebuggerFrame(true, url).setVisible(true);
}
public void skip() {
flowController.skip(currentRunningStep + 1);
try {
int lineStartOffset = scriptEditorTA.getLineStartOffset(currentRunningStep + 1);
for (GutterIconInfo info : scriptEditorScrollPane.getGutter().getAllTrackingIcons()) {
if (info.getMarkedOffset() == lineStartOffset && info.getIcon() == skippedIcon) {
scriptEditorScrollPane.getGutter().removeTrackingIcon(info);
}
}
scriptEditorScrollPane.getGutter().addOffsetTrackingIcon(scriptEditorTA.getLineStartOffset(currentRunningStep + 1), skippedIcon);
} catch (BadLocationException e) {
e.printStackTrace();
}
flowController.doNext();
}
public void toggleBreakPoint() {
try {
if (multiSelect) {
for (int line = multiSelectStart; line <= multiSelectEnd; line++) {
scriptEditorScrollPane.getGutter().toggleBookmark(line);
}
} else {
int line = scriptEditorTA.getCaretLineNumber();
scriptEditorScrollPane.getGutter().toggleBookmark(line);
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public void toggleSkip() {
if (multiSelect) {
for (int line = multiSelectStart; line <= multiSelectEnd; line++) {
doToggleSkip(line);
}
} else {
int line = scriptEditorTA.getCaretLineNumber();
doToggleSkip(line);
}
}
private void doToggleSkip(int line) {
try {
boolean found = false;
for (GutterIconInfo info : scriptEditorScrollPane.getGutter().getAllTrackingIcons()) {
if (scriptEditorTA.getLineOfOffset(info.getMarkedOffset()) == line && info.getIcon() == skippedIcon) {
scriptEditorScrollPane.getGutter().removeTrackingIcon(info);
found = true;
}
}
if (!found) {
scriptEditorScrollPane.getGutter().addOffsetTrackingIcon(scriptEditorTA.getLineStartOffset(line), skippedIcon);
}
if (flowController != null) {
if (flowController.getSkipList().contains(line)) {
flowController.removeSkip(line);
} else {
flowController.skip(line);
}
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public RequestResponsePanel getRequestResponsePanel() {
return requestResponsePanel;
}
}