mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GT-3035 - Restore Integration Tests - restored missing test files; fast
tests
This commit is contained in:
parent
822e5a0610
commit
4dc8e77172
45 changed files with 6609 additions and 0 deletions
|
@ -0,0 +1,74 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.app.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||
|
||||
public class PseudoDisassemblerTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||
|
||||
private ProgramBuilder programBuilder;// Instructions are 2-byte aligned
|
||||
private Program program;
|
||||
private PseudoDisassembler disassembler;
|
||||
|
||||
private int txId;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
programBuilder = new ProgramBuilder("Test", ProgramBuilder._ARM);
|
||||
program = programBuilder.getProgram();
|
||||
txId = program.startTransaction("Add Memory");// leave open until tearDown
|
||||
programBuilder.createMemory(".text", "0", 64).setExecute(true);// initialized
|
||||
programBuilder.createUninitializedMemory(".unint", "0x40", 64).setExecute(true);// uninitialized
|
||||
programBuilder.createUninitializedMemory(".dat", "0x80", 64);// no-execute
|
||||
programBuilder.createMemory(".text2", "0x3e0", 0x800).setExecute(true);// initialized
|
||||
|
||||
disassembler = new PseudoDisassembler(program);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (program != null) {
|
||||
program.endTransaction(txId, true);
|
||||
}
|
||||
if (programBuilder != null) {
|
||||
programBuilder.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringArmSeparator() throws Exception {
|
||||
programBuilder.setBytes("0", "08 f8 00 00 40 00");// strb.w r0,[r8,r0,0x0]
|
||||
programBuilder.setRegisterValue("TMode", "0", "1", 1);
|
||||
PseudoInstruction instr =
|
||||
disassembler.disassemble(program.getAddressFactory().getAddress("0"));
|
||||
|
||||
String str = instr.toString();
|
||||
assertEquals("strb.w r0,[r8,r0,lsl #0x0]", str);// wan't to make sure all markup is printed
|
||||
|
||||
programBuilder.setBytes("0", "00 f0 20 03");// nopeq
|
||||
programBuilder.setRegisterValue("TMode", "0", "1", 0);
|
||||
instr = disassembler.disassemble(program.getAddressFactory().getAddress("0"));
|
||||
|
||||
str = instr.toString();
|
||||
assertEquals("nopeq", str);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 docking.widgets.imagepanel;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.awt.Image;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import docking.test.AbstractDockingTest;
|
||||
import resources.ResourceManager;
|
||||
import resources.icons.EmptyIcon;
|
||||
|
||||
public class ImagePanelTest extends AbstractDockingTest {
|
||||
|
||||
private JFrame frame;
|
||||
private ImagePanel imagePanel;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Icon emptyIcon = new EmptyIcon(32, 32);
|
||||
Image emptyImage = ResourceManager.getImageIcon(emptyIcon).getImage();
|
||||
imagePanel = new ImagePanel(emptyImage);
|
||||
|
||||
frame = new JFrame("ImagePanel Test");
|
||||
frame.getContentPane().add(imagePanel);
|
||||
frame.setSize(400, 400);
|
||||
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
imagePanel.setZoomFactor(1.0f);
|
||||
|
||||
assertTrue("Unable to reset zoom factor",
|
||||
Float.compare(imagePanel.getZoomFactor(), 1.0f) == 0);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZoom_Neutral() {
|
||||
reset();
|
||||
|
||||
imagePanel.setZoomFactor(1.0f);
|
||||
|
||||
assertTrue("Zoom factor not set to 1.0x",
|
||||
Float.compare(imagePanel.getZoomFactor(), 1.0f) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZoom_10Point0f() {
|
||||
reset();
|
||||
|
||||
imagePanel.setZoomFactor(10.0f);
|
||||
|
||||
assertTrue("Zoom factor not set to 10.0x",
|
||||
Float.compare(imagePanel.getZoomFactor(), 10.0f) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZoom_0Point05() {
|
||||
reset();
|
||||
|
||||
imagePanel.setZoomFactor(0.05f);
|
||||
|
||||
assertTrue("Zoom factor not set to 0.05x",
|
||||
Float.compare(imagePanel.getZoomFactor(), 0.05f) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZoom_20Point0() {
|
||||
reset();
|
||||
|
||||
imagePanel.setZoomFactor(20.0f);
|
||||
|
||||
assertTrue("Zoom factor not set to 20.0x; should be 10.0x",
|
||||
Float.compare(imagePanel.getZoomFactor(), 10.0f) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZoom_0Point001() {
|
||||
reset();
|
||||
|
||||
imagePanel.setZoomFactor(0.001f);
|
||||
|
||||
assertTrue("Zoom factor not set to 0.001x; should be 0.05x",
|
||||
Float.compare(imagePanel.getZoomFactor(), 0.05f) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZoom_3Point75() {
|
||||
reset();
|
||||
|
||||
imagePanel.setZoomFactor(3.75f);
|
||||
|
||||
assertTrue("Zoom factor not set to 3.75x; should be 4.0x",
|
||||
Float.compare(imagePanel.getZoomFactor(), 4.0f) == 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,519 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 docking.widgets.textfield;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.RenderingHints.Key;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.*;
|
||||
import java.awt.image.renderable.RenderableImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.DebugGraphics;
|
||||
import javax.swing.RepaintManager;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HexOrDecimalInputTest {
|
||||
|
||||
@Test
|
||||
public void testSetAllowNegative() {
|
||||
HexOrDecimalInput input = new HexOrDecimalInput();
|
||||
|
||||
Long newValue = -1L;
|
||||
input.setValue(newValue);
|
||||
|
||||
assertThat(input.getValue(), is(newValue));
|
||||
|
||||
input.setAllowNegative(false);
|
||||
assertThat(input.getValue(), nullValue());
|
||||
|
||||
newValue = 20L;
|
||||
input.setValue(newValue);
|
||||
assertThat(input.getValue(), is(newValue));
|
||||
|
||||
newValue = -100L;
|
||||
input.setValue(newValue);
|
||||
assertThat(input.getValue(), nullValue());
|
||||
|
||||
input.setAllowNegative(true);
|
||||
newValue = -100L;
|
||||
input.setValue(newValue);
|
||||
assertThat(input.getValue(), is(newValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomPaint() {
|
||||
|
||||
HexOrDecimalInput input = new HexOrDecimalInput();
|
||||
RepaintManager repaintManager = RepaintManager.currentManager(input);
|
||||
repaintManager.setDoubleBufferingEnabled(false);
|
||||
|
||||
SpyPrintStream spy = new SpyPrintStream();
|
||||
DebugGraphics.setLogStream(spy);
|
||||
|
||||
DebugGraphics debugGraphics = new DebugGraphics(scratchGraphics());
|
||||
debugGraphics.setDebugOptions(DebugGraphics.LOG_OPTION);
|
||||
|
||||
Graphics2D g2d = new Graphics2DAdapter(debugGraphics);
|
||||
input.paintComponent(g2d);
|
||||
assertThat(spy.toString(), CoreMatchers.containsString("Dec"));
|
||||
|
||||
spy.reset();
|
||||
input.setHexMode();
|
||||
input.paintComponent(g2d);
|
||||
assertThat(spy.toString(), CoreMatchers.containsString("Hex"));
|
||||
|
||||
spy.reset();
|
||||
input.setDecimalMode();
|
||||
input.paintComponent(g2d);
|
||||
assertThat(spy.toString(), CoreMatchers.containsString("Dec"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToggleHexModeFromKeybinding() {
|
||||
HexOrDecimalInput input = new HexOrDecimalInput();
|
||||
Long value = 10L;
|
||||
input.setValue(value);
|
||||
|
||||
assertThat(input.getValue(), is(value));
|
||||
|
||||
toggleMode(input);
|
||||
|
||||
assertThat(input.getValue(), is(0xAL));
|
||||
|
||||
toggleMode(input);
|
||||
|
||||
assertThat(input.getValue(), is(value));
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
private void toggleMode(final HexOrDecimalInput input) {
|
||||
KeyEvent event = new KeyEvent(input, 0, System.currentTimeMillis(), 0, KeyEvent.VK_M, 'm');
|
||||
KeyListener[] keyListeners = input.getKeyListeners();
|
||||
for (KeyListener listener : keyListeners) {
|
||||
listener.keyPressed(event);
|
||||
}
|
||||
}
|
||||
|
||||
private Graphics scratchGraphics() {
|
||||
BufferedImage image = new BufferedImage(100, 20, BufferedImage.TYPE_INT_BGR);
|
||||
return image.getGraphics();
|
||||
}
|
||||
|
||||
private static class SpyPrintStream extends PrintStream {
|
||||
private static ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
SpyPrintStream() {
|
||||
super(baos);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
baos.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return baos.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An adapter to turn a Graphics into a Graphics2D. This implementation satisfies the base
|
||||
* methods needed for the test. So, many operations are stubbed or are exceptional.
|
||||
*/
|
||||
private static class Graphics2DAdapter extends Graphics2D {
|
||||
|
||||
private Graphics delegate;
|
||||
|
||||
Graphics2DAdapter(Graphics g) {
|
||||
this.delegate = g;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Shape s) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, int x, int y) {
|
||||
delegate.drawString(str, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, float x, float y) {
|
||||
delegate.drawString(str, (int) x, (int) y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, int x, int y) {
|
||||
delegate.drawString(iterator, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, float x, float y) {
|
||||
delegate.drawString(iterator, (int) x, (int) y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGlyphVector(GlyphVector g, float x, float y) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(Shape s) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComposite(Composite comp) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaint(Paint paint) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStroke(Stroke s) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHint(Key hintKey, Object hintValue) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRenderingHint(Key hintKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHints(Map<?, ?> hints) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRenderingHints(Map<?, ?> hints) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderingHints getRenderingHints() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(int x, int y) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(double tx, double ty) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta, double x, double y) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scale(double sx, double sy) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shear(double shx, double shy) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(AffineTransform Tx) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform(AffineTransform Tx) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getTransform() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint getPaint() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Composite getComposite() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color color) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stroke getStroke() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clip(Shape s) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontRenderContext getFontRenderContext() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create() {
|
||||
return delegate.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColor() {
|
||||
return delegate.getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(Color c) {
|
||||
delegate.setColor(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaintMode() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setXORMode(Color c1) {
|
||||
delegate.setXORMode(c1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Font getFont() {
|
||||
return delegate.getFont();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFont(Font font) {
|
||||
delegate.setFont(font);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics(Font f) {
|
||||
return delegate.getFontMetrics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getClipBounds() {
|
||||
return delegate.getClipBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clipRect(int x, int y, int width, int height) {
|
||||
delegate.clipRect(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip(int x, int y, int width, int height) {
|
||||
delegate.setClip(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getClip() {
|
||||
return delegate.getClip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip(Shape clip) {
|
||||
delegate.setClip(clip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
|
||||
delegate.copyArea(x, y, width, height, dx, dy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(int x1, int y1, int x2, int y2) {
|
||||
delegate.drawLine(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect(int x, int y, int width, int height) {
|
||||
delegate.fillRect(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRect(int x, int y, int width, int height) {
|
||||
delegate.clearRect(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRoundRect(int x, int y, int width, int height, int arcWidth,
|
||||
int arcHeight) {
|
||||
delegate.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRoundRect(int x, int y, int width, int height, int arcWidth,
|
||||
int arcHeight) {
|
||||
delegate.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOval(int x, int y, int width, int height) {
|
||||
delegate.drawOval(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillOval(int x, int y, int width, int height) {
|
||||
delegate.fillOval(x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
||||
delegate.drawArc(x, y, width, height, startAngle, arcAngle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
|
||||
delegate.fillArc(x, y, width, height, startAngle, arcAngle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
|
||||
delegate.drawPolyline(xPoints, yPoints, nPoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
|
||||
delegate.drawPolygon(xPoints, yPoints, nPoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
|
||||
delegate.fillPolygon(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
|
||||
return delegate.drawImage(img, x, y, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height,
|
||||
ImageObserver observer) {
|
||||
return delegate.drawImage(img, x, y, width, height, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
|
||||
return delegate.drawImage(img, x, y, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor,
|
||||
ImageObserver observer) {
|
||||
return delegate.drawImage(img, x, y, width, height, bgcolor, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
|
||||
int sx2, int sy2, ImageObserver observer) {
|
||||
return delegate.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1,
|
||||
int sx2, int sy2, Color bgcolor, ImageObserver observer) {
|
||||
return delegate.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor,
|
||||
observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
delegate.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 docking.widgets.textfield;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.concurrent.atomic.AtomicIntegerArray;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import docking.test.AbstractDockingTest;
|
||||
|
||||
public class IntegerTextFieldTest extends AbstractDockingTest {
|
||||
|
||||
private JFrame frame;
|
||||
private IntegerTextField field;
|
||||
private JTextField textField;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
field = new IntegerTextField(10);
|
||||
field.setShowNumberMode(true);
|
||||
textField = (JTextField) field.getComponent();
|
||||
frame = new JFrame("Test");
|
||||
frame.getContentPane().add(field.getComponent());
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultState() {
|
||||
assertNull(field.getValue());// no value
|
||||
assertEquals(0, field.getIntValue());// the "int value" return for null is 0
|
||||
assertEquals(0, field.getLongValue());
|
||||
assertTrue(!field.isHexMode());
|
||||
assertNull(field.getMaxValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeValidDecimalNumber() {
|
||||
triggerText(textField, "123");
|
||||
assertEquals(123, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeValidHexNumber() {
|
||||
triggerText(textField, "0x2abcdef");
|
||||
assertEquals(0x2abcdef, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidCharsIgnored() {
|
||||
triggerText(textField, "123ghijklmnopqrstuvwxyz4");
|
||||
assertEquals(1234, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHexCharsIgnoredInDecimalMode() {
|
||||
assertTrue(!field.isHexMode());
|
||||
triggerText(textField, "123ghijklmnopqrstuvwxyz4");
|
||||
assertEquals(1234, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXchangesHexMode() {
|
||||
assertTrue(!field.isHexMode());
|
||||
triggerText(textField, "0");
|
||||
assertTrue(!field.isHexMode());
|
||||
triggerText(textField, "x");
|
||||
assertTrue(field.isHexMode());
|
||||
triggerBackspaceKey(textField);
|
||||
assertTrue(!field.isHexMode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHexModeWithoutPrefix() {
|
||||
triggerText(textField, "abc");// not allowed when using hex prefix, so expect empty
|
||||
assertEquals(null, field.getValue());
|
||||
|
||||
field.setAllowsHexPrefix(false);
|
||||
field.setHexMode();
|
||||
triggerText(textField, "abc");
|
||||
assertEquals(0xabc, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegative() {
|
||||
triggerText(textField, "-123");
|
||||
assertEquals(-123, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeHex() {
|
||||
triggerText(textField, "-0xa");
|
||||
assertEquals(-10, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeNotAllowed() {
|
||||
field.setAllowNegativeValues(false);
|
||||
triggerText(textField, "-123");
|
||||
assertEquals(123, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetNegativeWithCurrentNegativeValue() {
|
||||
field.setValue(-123);
|
||||
field.setAllowNegativeValues(false);
|
||||
assertEquals(null, field.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMax() {
|
||||
field.setMaxValue(BigInteger.valueOf(13l));
|
||||
triggerText(textField, "12");
|
||||
assertEquals(12, field.getIntValue());
|
||||
|
||||
field.setValue(null);
|
||||
triggerText(textField, "13");
|
||||
assertEquals(13, field.getIntValue());
|
||||
|
||||
field.setValue(null);
|
||||
triggerText(textField, "14");// four should be ignored
|
||||
assertEquals(1, field.getIntValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMaxToValueSmallerThanCurrent() {
|
||||
field.setValue(500);
|
||||
field.setMaxValue(BigInteger.valueOf(400));
|
||||
assertEquals(400, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxInHex() {
|
||||
field.setMaxValue(BigInteger.valueOf(0xd));
|
||||
triggerText(textField, "0xc");
|
||||
assertEquals(12, field.getIntValue());
|
||||
|
||||
field.setValue(null);
|
||||
triggerText(textField, "0xd");
|
||||
assertEquals(13, field.getIntValue());
|
||||
|
||||
field.setValue(null);
|
||||
triggerText(textField, "0xe");// e should be ignored
|
||||
assertEquals(0, field.getIntValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitchingHexMode() {
|
||||
field.setValue(255);
|
||||
assertEquals("255", field.getText());
|
||||
field.setHexMode();
|
||||
assertEquals("0xff", field.getText());
|
||||
field.setDecimalMode();
|
||||
assertEquals("255", field.getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeListenerAfterValidInput() {
|
||||
TestChangeListener listener = new TestChangeListener();
|
||||
field.addChangeListener(listener);
|
||||
|
||||
triggerText(textField, "123");
|
||||
assertEquals(3, listener.count);
|
||||
assertEquals(1, listener.values.get(0));
|
||||
assertEquals(12, listener.values.get(1));
|
||||
assertEquals(123, listener.values.get(2));
|
||||
|
||||
triggerBackspaceKey(textField);
|
||||
assertEquals(12, listener.values.get(3));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeListenerAfterSwitchingModes() {
|
||||
triggerText(textField, "123");
|
||||
|
||||
TestChangeListener listener = new TestChangeListener();
|
||||
field.addChangeListener(listener);
|
||||
|
||||
setHexMode();
|
||||
|
||||
assertEquals(2, listener.count);
|
||||
assertEquals(123, listener.values.get(1));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeHexFromValue() {
|
||||
field.setValue(-255);
|
||||
setHexMode();
|
||||
assertEquals("-0xff", field.getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullValue() {
|
||||
field.setValue(12);
|
||||
assertEquals("12", field.getText());
|
||||
field.setValue(null);
|
||||
assertEquals("", field.getText());
|
||||
assertEquals(0, field.getIntValue());
|
||||
assertEquals(0l, field.getLongValue());
|
||||
assertEquals(null, field.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHexValueInDontRequireHexPrefixMode() {
|
||||
field.setAllowsHexPrefix(false);
|
||||
field.setHexMode();
|
||||
field.setValue(255);
|
||||
assertEquals("ff", field.getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetNotAllowNegativeModeWhileCurrentValueIsNegative() {
|
||||
field.setValue(-10);
|
||||
field.setAllowNegativeValues(false);
|
||||
assertEquals("", field.getText());
|
||||
assertEquals(0, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLongValue() {
|
||||
field.setValue(100L);
|
||||
assertEquals(100L, field.getLongValue());
|
||||
assertEquals(100, field.getIntValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettingNegativeNumberWhenNegativesArentAllowed() {
|
||||
field.setValue(10);
|
||||
field.setAllowNegativeValues(false);
|
||||
field.setValue(-10);
|
||||
assertEquals("", field.getText());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUseHexPrefixUpdatesTextField() {
|
||||
field.setAllowsHexPrefix(false);
|
||||
field.setHexMode();
|
||||
field.setValue(255);
|
||||
assertEquals("ff", field.getText());
|
||||
field.setAllowsHexPrefix(true);
|
||||
assertEquals("0xff", field.getText());
|
||||
}
|
||||
|
||||
private void setHexMode() {
|
||||
runSwing(() -> field.setHexMode());
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
class TestChangeListener implements ChangeListener {
|
||||
volatile int count;
|
||||
private AtomicIntegerArray values = new AtomicIntegerArray(10);
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
values.set(count++, field.getIntValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.util.task;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import docking.test.AbstractDockingTest;
|
||||
import generic.test.AbstractGenericTest;
|
||||
|
||||
public class TaskMonitorSplitterTest extends AbstractDockingTest {
|
||||
TaskMonitor baseMonitor;
|
||||
|
||||
public TaskMonitorSplitterTest() {
|
||||
super();
|
||||
baseMonitor = new TaskMonitorComponent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicUse() {
|
||||
TaskMonitor[] monitors = TaskMonitorSplitter.splitTaskMonitor(baseMonitor, 4);
|
||||
|
||||
monitors[0].initialize(100);
|
||||
monitors[0].setProgress(1);
|
||||
assertEquals(1, monitors[0].getProgress());
|
||||
assertEquals(TaskMonitorSplitter.MONITOR_SIZE / 400, baseMonitor.getProgress());
|
||||
|
||||
monitors[0].incrementProgress(1);
|
||||
assertEquals(2 * TaskMonitorSplitter.MONITOR_SIZE / 400, baseMonitor.getProgress());
|
||||
|
||||
monitors[0].setProgress(10);
|
||||
assertEquals(10 * TaskMonitorSplitter.MONITOR_SIZE / 400, baseMonitor.getProgress());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxSettings() {
|
||||
TaskMonitor[] monitors = TaskMonitorSplitter.splitTaskMonitor(baseMonitor, 4);
|
||||
|
||||
monitors[0].initialize(100);
|
||||
monitors[0].setProgress(50);
|
||||
assertEquals(50 * TaskMonitorSplitter.MONITOR_SIZE / 400, baseMonitor.getProgress());
|
||||
|
||||
monitors[0].setMaximum(25);
|
||||
assertEquals(25, monitors[0].getMaximum());
|
||||
assertEquals(TaskMonitorSplitter.MONITOR_SIZE / 4, baseMonitor.getProgress());
|
||||
|
||||
monitors[0].setMaximum(100);
|
||||
assertEquals(25 * TaskMonitorSplitter.MONITOR_SIZE / 400, baseMonitor.getProgress());
|
||||
|
||||
}
|
||||
|
||||
}
|
196
Ghidra/Framework/Help/src/test/java/help/AbstractHelpTest.java
Normal file
196
Ghidra/Framework/Help/src/test/java/help/AbstractHelpTest.java
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 help;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
public abstract class AbstractHelpTest extends AbstractGenericTest {
|
||||
|
||||
protected static final String HELP_FILENAME_PREFIX = "Fake";
|
||||
protected static final String HELP_FILENAME = HELP_FILENAME_PREFIX + ".html";
|
||||
|
||||
private Path testTempDir;
|
||||
|
||||
public AbstractHelpTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
testTempDir = Files.createTempDirectory(testName.getMethodName());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
FileUtilities.deleteDir(testTempDir.toFile());
|
||||
}
|
||||
|
||||
protected Path createHelpBuildOutputDir() throws IOException {
|
||||
Path out = testTempDir.resolve("build/help/main/help");
|
||||
Files.createDirectories(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
protected Path createFakeHelpTopic(Path helpDir) throws IOException {
|
||||
return createFakeHelpTopic("FakeTopic", helpDir);
|
||||
}
|
||||
|
||||
protected Path createFakeHelpTopic(String topicName, Path helpDir) throws IOException {
|
||||
Path topicsDir = helpDir.resolve("topics");
|
||||
Path fakeTopicDir = topicsDir.resolve(topicName);
|
||||
Files.createDirectories(fakeTopicDir);
|
||||
return fakeTopicDir;
|
||||
}
|
||||
|
||||
protected Path createTempHelpDir() throws IOException {
|
||||
Path helpDir = testTempDir.resolve("help");
|
||||
Files.createDirectory(helpDir);
|
||||
return helpDir;
|
||||
}
|
||||
|
||||
protected void addRequiredHelpDirStructure(Path helpDir) throws IOException {
|
||||
|
||||
// HelpFile wants to read one of these, so put one there
|
||||
createEmpty_TOC_Source_File(helpDir);
|
||||
createSharedDir(helpDir);
|
||||
}
|
||||
|
||||
protected Path createSharedDir(Path helpDir) throws IOException {
|
||||
Path sharedDir = helpDir.resolve("shared");
|
||||
Files.createDirectory(sharedDir);
|
||||
|
||||
Path css = sharedDir.resolve("Frontpage.css");
|
||||
Files.createFile(css);
|
||||
|
||||
Path png = sharedDir.resolve("test.png");
|
||||
Files.createFile(png);
|
||||
|
||||
return sharedDir;
|
||||
}
|
||||
|
||||
protected Path createEmpty_TOC_Source_File(Path dir) throws IOException {
|
||||
|
||||
Path fullTOCPath = dir.resolve("TOC_Source.xml");
|
||||
Path file = Files.createFile(fullTOCPath);
|
||||
|
||||
//@formatter:off
|
||||
String TOCXML = "<?xml version='1.0' encoding='ISO-8859-1' ?>\n" +
|
||||
"<!-- Auto-generated on Fri Apr 03 09:37:08 EDT 2015 -->\n\n" +
|
||||
|
||||
"<tocroot>\n" +
|
||||
"</tocroot>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, TOCXML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
protected Path createHelpContent(Path topic, String anchor) throws IOException {
|
||||
Path htmlPath = topic.resolve(HELP_FILENAME);
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
if (anchor == null) {
|
||||
anchor = "Default_Anchor";
|
||||
}
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/Frontpage.css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
|
||||
"<BODY>\n" +
|
||||
" <H1><A name=\""+anchor+"\"></A>Configure Tool</H1>\n" +
|
||||
" Some text with reference to shared image <IMG src=\"../../shared/test.png\">\n" +
|
||||
" \n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
protected Path createHelpContent_WithReferenceHREF(Path topic, String HREF) throws IOException {
|
||||
Path htmlPath = topic.resolve(HELP_FILENAME);
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
assertNotNull("Must specify the A tag HREF attribute", HREF);
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/Frontpage.css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
|
||||
"<BODY>\n" +
|
||||
" <H1><A name=\"Fake_Anchor\"></A>Configure Tool</H1>\n" +
|
||||
" And this is a link <A HREF=\""+HREF+"\">Click Me</A>" +
|
||||
" \n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
protected Path createHelpContent_WithReferenceIMG_SRC(Path topic, String SRC)
|
||||
throws IOException {
|
||||
Path htmlPath = topic.resolve(HELP_FILENAME);
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
assertNotNull("Must specify the A tag SRC attribute", SRC);
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/Frontpage.css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
|
||||
"<BODY>\n" +
|
||||
" <H1><A name=\"Fake_Anchor\"></A>Configure Tool</H1>\n" +
|
||||
" Some text with reference to shared image <IMG src=\""+SRC+"\">\n" +
|
||||
" \n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
protected void copy(Path from, Path to) throws Exception {
|
||||
|
||||
FileUtilities.copyDir(from.toFile(), to.toFile(), null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 help;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class HelpBuildUtilsTest extends AbstractHelpTest {
|
||||
|
||||
private static final String HELP_TOPIC_PATH = "/some/fake/path/to/help/topics";
|
||||
private static final String TOPIC_AND_FILENAME = "FooTopic/FooFile.html";
|
||||
private static final String HTML_FILE_PATH = HELP_TOPIC_PATH + '/' + TOPIC_AND_FILENAME;
|
||||
|
||||
public HelpBuildUtilsTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRelativeHelpPath() {
|
||||
String relativeString = "help/topics/FooTopic/FooFile.html";
|
||||
Path path = Paths.get("/some/fake/path/to/" + relativeString);
|
||||
Path relative = HelpBuildUtils.relativizeWithHelpTopics(path);
|
||||
assertEquals(relativeString, relative.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRelativeHelpPath_NoHelpTopicInPath() {
|
||||
String invalidRelativeString = "help/topicz/" + TOPIC_AND_FILENAME;
|
||||
Path path = Paths.get("/some/fake/path/to/" + invalidRelativeString);
|
||||
Path relative = HelpBuildUtils.relativizeWithHelpTopics(path);
|
||||
assertNull(relative);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocateReference_Local_HelpSystemSyntax() throws URISyntaxException {
|
||||
Path sourceFile = Paths.get(HTML_FILE_PATH);
|
||||
String reference = "help/topics/shared/foo.png";
|
||||
Path resolved = HelpBuildUtils.locateReference(sourceFile, reference);
|
||||
assertEquals("Help System syntax was not preserved", Paths.get(reference), resolved);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocateReference_Local_RelativeSyntax() throws URISyntaxException {
|
||||
Path sourceFile = Paths.get(HTML_FILE_PATH);
|
||||
String reference = "../shared/foo.png";// go up one to the help dir
|
||||
Path resolved = HelpBuildUtils.locateReference(sourceFile, reference);
|
||||
assertEquals("Relative syntax did not locate file",
|
||||
Paths.get(HELP_TOPIC_PATH + "/shared/foo.png"), resolved);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocateReference_Remote() throws URISyntaxException {
|
||||
Path sourceFile = Paths.get(HTML_FILE_PATH);
|
||||
String reference = "http://some.fake.server/foo.png";
|
||||
Path resolved = HelpBuildUtils.locateReference(sourceFile, reference);
|
||||
assertNull(resolved);
|
||||
boolean isRemote = HelpBuildUtils.isRemote(reference);
|
||||
assertTrue(isRemote);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocateReferences_Icons() throws URISyntaxException {
|
||||
Path sourceFile = Paths.get(HTML_FILE_PATH);
|
||||
String reference = "Icons.REFRESH_ICON"; // see Icons class
|
||||
ImageLocation location = HelpBuildUtils.locateImageReference(sourceFile, reference);
|
||||
Path resolved = location.getResolvedPath();
|
||||
String name = resolved.getFileName().toString();
|
||||
assertEquals("Help System syntax was not preserved", "reload3.png", name);
|
||||
assertTrue(location.isRuntime());
|
||||
assertFalse(location.isRemote());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocateReferences_Icons_BadName() throws URISyntaxException {
|
||||
Path sourceFile = Paths.get(HTML_FILE_PATH);
|
||||
String reference = "Icons.REFRESH_ICON_BAD"; // non-existent
|
||||
ImageLocation location = HelpBuildUtils.locateImageReference(sourceFile, reference);
|
||||
Path resolved = location.getResolvedPath();
|
||||
assertNull(resolved);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,418 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 help;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.help.HelpSet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import help.validator.LinkDatabase;
|
||||
import help.validator.location.*;
|
||||
import help.validator.model.*;
|
||||
|
||||
public class OverlayHelpTreeTest {
|
||||
|
||||
@Test
|
||||
public void testSourceTOCFileThatDependsUponPreBuiltHelp() {
|
||||
//
|
||||
// We want to make sure the overlay tree will properly resolve help TOC items being
|
||||
// built from TOC_Source.xml files when that file uses <TOCREF> items that are defined
|
||||
// in a help <TOCITEM> that lives inside of a pre-built jar file.
|
||||
//
|
||||
/*
|
||||
|
||||
Example makeup we will create:
|
||||
|
||||
PreBuild_TOC.xml
|
||||
|
||||
<tocitem id="root" target="fake">
|
||||
<tocitem id="child_1" target="fake" />
|
||||
</tocitem>
|
||||
|
||||
|
||||
TOC_Source.xml
|
||||
|
||||
<tocref id="root">
|
||||
<tocref="child_1">
|
||||
<tocdef id="child_2" target="fake" />
|
||||
</tocref>
|
||||
</tocref>
|
||||
|
||||
*/
|
||||
|
||||
TOCItemExternal root = externalItem("root");
|
||||
TOCItemExternal child_1 = externalItem(root, "child_1");
|
||||
|
||||
Path tocSourceFile = Paths.get("/fake/path_2/TOC_Source.xml");
|
||||
String root_ID = root.getIDAttribute();
|
||||
TOCItemReference root_ref = referenceItem(root_ID, tocSourceFile);
|
||||
|
||||
String child_1_ID = child_1.getIDAttribute();
|
||||
TOCItemReference child_1_ref = referenceItem(root_ref, child_1_ID, tocSourceFile);
|
||||
|
||||
TOCItemDefinition child_2 = definitionItem(child_1_ref, "child_2", tocSourceFile);
|
||||
|
||||
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
||||
tocProvider.addExternal(root);
|
||||
tocProvider.addExternal(child_1);
|
||||
tocProvider.addDefinition(child_2);
|
||||
|
||||
TOCSpyWriter spy = printOverlayTree(tocProvider, tocSourceFile);
|
||||
|
||||
assertNodeCount(spy, 3);
|
||||
assertOrder(spy, 1, root);
|
||||
assertOrder(spy, 2, child_1);
|
||||
assertOrder(spy, 3, child_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSourceTOCFileThatDependsUponPreBuiltHelp_MultiplePreBuiltInputs() {
|
||||
//
|
||||
// We want to make sure the overlay tree will properly resolve help TOC items being
|
||||
// built from TOC_Source.xml files when that file uses <TOCREF> items that are defined
|
||||
// in a help <TOCITEM> that lives inside of multiple pre-built jar files.
|
||||
//
|
||||
/*
|
||||
|
||||
Example makeup we will create:
|
||||
|
||||
PreBuild_TOC.xml
|
||||
|
||||
<tocitem id="root" target="fake">
|
||||
<tocitem id="child_1" target="fake">
|
||||
<tocitem="prebuilt_a_child" target="fake" />
|
||||
</tocitem>
|
||||
</tocitem>
|
||||
|
||||
Another PreBuild_TOC.xml
|
||||
|
||||
<tocitem id="root" target="fake">
|
||||
<tocitem id="child_1" target="fake">
|
||||
<tocitem="prebuilt_b_child" target="fake" />
|
||||
</tocitem>
|
||||
</tocitem>
|
||||
|
||||
|
||||
TOC_Source.xml
|
||||
|
||||
<tocref id="root">
|
||||
<tocref="child_1">
|
||||
<tocdef id="child_2" target="fake" />
|
||||
</tocref>
|
||||
</tocref>
|
||||
|
||||
*/
|
||||
|
||||
TOCItemExternal root_a = externalItem("root");
|
||||
TOCItemExternal child_1_a = externalItem(root_a, "child_1");
|
||||
TOCItemExternal prebuilt_a_child = externalItem(child_1_a, "prebuilt_a_child");
|
||||
|
||||
// note: same ID values, since they represent the same nodes, but from different TOC files
|
||||
TOCItemExternal root_b = externalItemAlt(null, "root");
|
||||
TOCItemExternal child_1_b = externalItemAlt(root_b, "child_1");
|
||||
TOCItemExternal prebuilt_b_child = externalItemAlt(child_1_b, "prebuilt_b_child");
|
||||
|
||||
Path tocSourceFile = Paths.get("/fake/path_2/TOC_Source.xml");
|
||||
String root_ID = root_a.getIDAttribute();
|
||||
TOCItemReference root_ref = referenceItem(root_ID, tocSourceFile);
|
||||
|
||||
String child_1_ID = child_1_a.getIDAttribute();
|
||||
TOCItemReference child_1_ref = referenceItem(root_ref, child_1_ID, tocSourceFile);
|
||||
|
||||
TOCItemDefinition child_2 = definitionItem(child_1_ref, "child_2", tocSourceFile);
|
||||
|
||||
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
||||
tocProvider.addExternal(root_a);
|
||||
tocProvider.addExternal(root_b);
|
||||
tocProvider.addExternal(child_1_a);
|
||||
tocProvider.addExternal(child_1_b);
|
||||
tocProvider.addExternal(prebuilt_a_child);
|
||||
tocProvider.addExternal(prebuilt_b_child);
|
||||
tocProvider.addDefinition(child_2);
|
||||
|
||||
TOCSpyWriter spy = printOverlayTree(tocProvider, tocSourceFile);
|
||||
|
||||
assertNodeCount(spy, 3);
|
||||
assertOrder(spy, 1, root_a);// could also be root_b, same ID
|
||||
assertOrder(spy, 2, child_1_a);// could also be child_1_b, same ID
|
||||
assertOrder(spy, 3, child_2);
|
||||
|
||||
// note: prebuilt_a_child and prebuilt_b_child don't get output, since they do not have
|
||||
// the same TOC file ID as the help file being processed (in other words, they don't
|
||||
// live in the TOC_Source.xml being processes, so they are not part of the output).
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSourceTOCFileThatDependsAnotherTOCSourceFile() {
|
||||
|
||||
/*
|
||||
|
||||
The first source file defines attributes that the second file references.
|
||||
|
||||
Example makeup we will create:
|
||||
|
||||
TOC_Source.xml
|
||||
|
||||
<tocdef id="root" target="fake">
|
||||
<tocdef id="child_1" target="fake" />
|
||||
</tocdef>
|
||||
|
||||
|
||||
Another TOC_Source.xml
|
||||
|
||||
<tocref id="root">
|
||||
<tocref="child_1">
|
||||
<tocdef id="child_2" target="fake" />
|
||||
</tocref>
|
||||
</tocref>
|
||||
|
||||
*/
|
||||
|
||||
Path toc_1 = Paths.get("/fake/path_1/TOC_Source.xml");
|
||||
TOCItemDefinition root = definitionItem("root", toc_1);
|
||||
TOCItemDefinition child_1 = definitionItem(root, "child_1", toc_1);
|
||||
|
||||
Path toc_2 = Paths.get("/fake/path_2/TOC_Source.xml");
|
||||
String root_ID = root.getIDAttribute();
|
||||
String child_1_ID = child_1.getIDAttribute();
|
||||
|
||||
TOCItemReference root_ref = referenceItem(root_ID, toc_2);
|
||||
TOCItemReference child_1_ref = referenceItem(root_ref, child_1_ID, toc_2);
|
||||
TOCItemDefinition child_2 = definitionItem(child_1_ref, "child_2", toc_2);
|
||||
|
||||
TOCItemProviderTestStub tocProvider = new TOCItemProviderTestStub();
|
||||
tocProvider.addDefinition(root);
|
||||
tocProvider.addDefinition(child_1);
|
||||
tocProvider.addDefinition(child_2);// in the second TOC file
|
||||
|
||||
TOCSpyWriter spy = printOverlayTree(tocProvider, toc_2);
|
||||
|
||||
assertNodeCount(spy, 3);
|
||||
assertOrder(spy, 1, root);
|
||||
assertOrder(spy, 2, child_1);
|
||||
assertOrder(spy, 3, child_2);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
private TOCSpyWriter printOverlayTree(TOCItemProviderTestStub tocItemProvider, Path tocFile) {
|
||||
|
||||
//
|
||||
// Create a test version of the LinkDatabase for the overlay tree, with test versions of
|
||||
// it's required TOC input file and HelpModuleLocation
|
||||
//
|
||||
GhidraTOCFileDummy toc = new GhidraTOCFileDummy(tocFile);
|
||||
OverlayHelpModuleLocationTestStub location = new OverlayHelpModuleLocationTestStub(toc);
|
||||
LinkDatabaseTestStub db = new LinkDatabaseTestStub(location);
|
||||
|
||||
// This is the class we are testing!!
|
||||
OverlayHelpTree overlayHelpTree = new OverlayHelpTree(tocItemProvider, db);
|
||||
|
||||
TOCSpyWriter spy = new TOCSpyWriter();
|
||||
String TOCID = tocFile.toUri().toString();
|
||||
overlayHelpTree.printTreeForID(spy, TOCID);
|
||||
|
||||
System.out.println(spy.toString());
|
||||
|
||||
return spy;
|
||||
}
|
||||
|
||||
private TOCItemDefinition definitionItem(String ID, Path tocSourceFile) {
|
||||
return definitionItem(null, ID, tocSourceFile);
|
||||
}
|
||||
|
||||
private TOCItemDefinition definitionItem(TOCItem parent, String ID, Path tocSourceFile) {
|
||||
String target = "fake";
|
||||
String sort = "";
|
||||
int line = 1;
|
||||
return new TOCItemDefinition(parent, tocSourceFile, ID, ID, target, sort, line);
|
||||
}
|
||||
|
||||
private TOCItemReference referenceItem(String referenceID, Path tocSourceFile) {
|
||||
return referenceItem(null, referenceID, tocSourceFile);
|
||||
}
|
||||
|
||||
private TOCItemReference referenceItem(TOCItem parent, String referenceID, Path tocSourceFile) {
|
||||
return new TOCItemReference(parent, tocSourceFile, referenceID, 1);
|
||||
}
|
||||
|
||||
private TOCItemExternal externalItem(String ID) {
|
||||
return externalItem(null, ID);
|
||||
}
|
||||
|
||||
private TOCItemExternal externalItem(TOCItem parent, String ID) {
|
||||
Path tocFile = Paths.get("/fake/path_1/PreBuild_TOC.xml");
|
||||
String target = "fake";
|
||||
String sort = "";
|
||||
int line = 1;
|
||||
return new TOCItemExternal(parent, tocFile, ID, ID, target, sort, line);
|
||||
}
|
||||
|
||||
private TOCItemExternal externalItemAlt(TOCItem parent, String ID) {
|
||||
Path tocFile = Paths.get("/fake/path_1/PreBuild_TOC.xml");
|
||||
String target = "fake";
|
||||
String sort = "";
|
||||
int line = 1;
|
||||
return new TOCItemExternal(parent, tocFile, ID, ID, target, sort, line);
|
||||
}
|
||||
|
||||
private void assertOrder(TOCSpyWriter spy, int ordinal, TOCItem item) {
|
||||
String ID = spy.getItem(ordinal - 1 /* make an index */);
|
||||
assertEquals("Did not find TOC item at expected index: " + ordinal, item.getIDAttribute(),
|
||||
ID);
|
||||
}
|
||||
|
||||
private void assertNodeCount(TOCSpyWriter spy, int count) {
|
||||
assertEquals("Did not get exactly one node per TOC item input", count, spy.getItemCount());
|
||||
}
|
||||
|
||||
private class TOCSpyWriter extends PrintWriter {
|
||||
|
||||
private StringWriter stringWriter;
|
||||
|
||||
private List<String> tocItems = new ArrayList<>();
|
||||
|
||||
public TOCSpyWriter() {
|
||||
super(new StringWriter(), true);
|
||||
stringWriter = ((StringWriter) out);
|
||||
}
|
||||
|
||||
String getItem(int position) {
|
||||
return tocItems.get(position);
|
||||
}
|
||||
|
||||
int getItemCount() {
|
||||
return tocItems.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(String s) {
|
||||
super.println(s);
|
||||
|
||||
s = s.trim();
|
||||
if (!s.startsWith("<tocitem")) {
|
||||
return;
|
||||
}
|
||||
|
||||
storeDisplayAttribute(s);
|
||||
}
|
||||
|
||||
private void storeDisplayAttribute(String s) {
|
||||
// create a pattern to pull out the display string
|
||||
Pattern p = Pattern.compile(".*display=\"(.*)\" toc_id.*");
|
||||
Matcher matcher = p.matcher(s.trim());
|
||||
|
||||
if (!matcher.matches()) {
|
||||
return;// not a TOC item
|
||||
}
|
||||
|
||||
String value = matcher.group(1);
|
||||
tocItems.add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return stringWriter.getBuffer().toString();
|
||||
}
|
||||
}
|
||||
|
||||
private class TOCItemProviderTestStub implements TOCItemProvider {
|
||||
|
||||
Map<String, TOCItemExternal> externals = new HashMap<>();
|
||||
Map<String, TOCItemDefinition> definitions = new HashMap<>();
|
||||
|
||||
void addExternal(TOCItemExternal item) {
|
||||
String displayText = item.getIDAttribute();
|
||||
externals.put(displayText, item);
|
||||
}
|
||||
|
||||
void addDefinition(TOCItemDefinition item) {
|
||||
String ID = item.getIDAttribute();
|
||||
definitions.put(ID, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TOCItemExternal> getTOCItemExternalsByDisplayMapping() {
|
||||
return externals;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TOCItemDefinition> getTOCItemDefinitionsByIDMapping() {
|
||||
return definitions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class LinkDatabaseTestStub extends LinkDatabase {
|
||||
|
||||
public LinkDatabaseTestStub(HelpModuleLocation loc) {
|
||||
super(HelpModuleCollection.fromHelpLocations(Collections.singleton(loc)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIDForLink(String target) {
|
||||
return "test_ID_" + target;
|
||||
}
|
||||
}
|
||||
|
||||
private class OverlayHelpModuleLocationTestStub extends HelpModuleLocationTestDouble {
|
||||
|
||||
OverlayHelpModuleLocationTestStub(GhidraTOCFileDummy toc) {
|
||||
super(Paths.get("/fake/help"));
|
||||
this.sourceTOCFile = toc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadHelpTopics() {
|
||||
// no! ...don't really go to the filesystem
|
||||
}
|
||||
|
||||
@Override
|
||||
public GhidraTOCFile loadSourceTOCFile() {
|
||||
return null;// we set this in the constructor
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpSet loadHelpSet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHelpInputSource() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class GhidraTOCFileDummy extends GhidraTOCFileTestDouble {
|
||||
|
||||
public GhidraTOCFileDummy(Path path) {
|
||||
super(path);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 help.validator.location;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import help.validator.location.HelpModuleLocation;
|
||||
|
||||
public abstract class HelpModuleLocationTestDouble extends HelpModuleLocation {
|
||||
|
||||
// this class exists to open up the package-level constructor
|
||||
public HelpModuleLocationTestDouble(Path source) {
|
||||
super(source);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 help.validator.model;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
public class AnchorDefinitionTest extends AbstractGenericTest {
|
||||
|
||||
public AnchorDefinitionTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileWithoutAnchor() {
|
||||
// this should generate and ID that is the filename only
|
||||
Path fullPath = Paths.get("/fake/full/path/help/topics/TopicName/HelpFilename.html"); // dir case
|
||||
AnchorDefinition def = new AnchorDefinition(fullPath, null, 1);
|
||||
assertEquals("TopicName_HelpFilename", def.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileInHelpTopicDir() {
|
||||
|
||||
Path fullPath = Paths.get("/fake/full/path/help/topics/TopicName/HelpFilename.html"); // dir case
|
||||
AnchorDefinition def = new AnchorDefinition(fullPath, "anchor_1", 1);
|
||||
assertEquals("TopicName_anchor_1", def.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileInHelpTopicJar() {
|
||||
Path fullPath = Paths.get("/help/topics/TopicName/HelpFilename.html"); // jar case
|
||||
AnchorDefinition def = new AnchorDefinition(fullPath, "anchor_1", 1);
|
||||
assertEquals("TopicName_anchor_1", def.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileInHelpDir_NotUnderHelpTopic() {
|
||||
Path fullPath = Paths.get("/fake/full/path/help/HelpFilename.html"); // dir case
|
||||
|
||||
try {
|
||||
new AnchorDefinition(fullPath, "anchor_1", 1);
|
||||
Assert.fail("Did not fail with file not living under a help topic directory");
|
||||
}
|
||||
catch (AssertException e) {
|
||||
// good
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* 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 help.validator.model;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class GhidraTOCFileTestDouble extends GhidraTOCFile {
|
||||
|
||||
// this class exists to open up constructor access
|
||||
public GhidraTOCFileTestDouble(Path sourceFile) {
|
||||
super(sourceFile);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 help.validator.model;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import help.AbstractHelpTest;
|
||||
import help.validator.*;
|
||||
import help.validator.location.DirectoryHelpModuleLocation;
|
||||
|
||||
public class HelpFileTest extends AbstractHelpTest {
|
||||
|
||||
@Test
|
||||
public void testGoodHTML() throws IOException {
|
||||
|
||||
Path helpDir = createTempHelpDir();
|
||||
addRequiredHelpDirStructure(helpDir);
|
||||
|
||||
Path topic = createFakeHelpTopic(helpDir);
|
||||
|
||||
DirectoryHelpModuleLocation helpLocation =
|
||||
new DirectoryHelpModuleLocation(helpDir.toFile());
|
||||
|
||||
Path html = createGoodHTMLFile(topic);
|
||||
new HelpFile(helpLocation, html);
|
||||
|
||||
// if we get here, then no exceptions happened
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHTML_InvalidStyleSheet() throws Exception {
|
||||
|
||||
Path helpDir = createTempHelpDir();
|
||||
addRequiredHelpDirStructure(helpDir);
|
||||
|
||||
Path topic = createFakeHelpTopic(helpDir);
|
||||
|
||||
DirectoryHelpModuleLocation helpLocation =
|
||||
new DirectoryHelpModuleLocation(helpDir.toFile());
|
||||
|
||||
Path html = createBadHTMLFile_InvalidStyleSheet(topic);
|
||||
|
||||
try {
|
||||
new HelpFile(helpLocation, html);
|
||||
fail("Parsing did not fail for invalid stylesheet");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// good
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHTML_InvalidAnchorRef_BadURI() throws Exception {
|
||||
|
||||
Path helpDir = createTempHelpDir();
|
||||
addRequiredHelpDirStructure(helpDir);
|
||||
|
||||
Path topic = createFakeHelpTopic(helpDir);
|
||||
|
||||
DirectoryHelpModuleLocation helpLocation =
|
||||
new DirectoryHelpModuleLocation(helpDir.toFile());
|
||||
|
||||
Path html = createBadHTMLFile_InvalidAnchor_BadURI(topic);
|
||||
|
||||
try {
|
||||
new HelpFile(helpLocation, html);
|
||||
fail("Parsing did not fail for invalid stylesheet");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// good
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHTML_InvalidAnchorRef_WrongAttribtues() throws Exception {
|
||||
// no 'name' or 'href' attribute
|
||||
Path helpDir = createTempHelpDir();
|
||||
addRequiredHelpDirStructure(helpDir);
|
||||
|
||||
Path topic = createFakeHelpTopic(helpDir);
|
||||
|
||||
DirectoryHelpModuleLocation helpLocation =
|
||||
new DirectoryHelpModuleLocation(helpDir.toFile());
|
||||
|
||||
Path html = createBadHTMLFile_InvalidAnchor_WrongAttributes(topic);
|
||||
|
||||
try {
|
||||
new HelpFile(helpLocation, html);
|
||||
fail("Parsing did not fail for invalid stylesheet");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// good
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadHTML_InvalidIMG_WrongAttribtues() throws Exception {
|
||||
// no 'src'
|
||||
Path helpDir = createTempHelpDir();
|
||||
addRequiredHelpDirStructure(helpDir);
|
||||
|
||||
Path topic = createFakeHelpTopic(helpDir);
|
||||
|
||||
DirectoryHelpModuleLocation helpLocation =
|
||||
new DirectoryHelpModuleLocation(helpDir.toFile());
|
||||
|
||||
Path html = createBadHTMLFile_InvalidIMG_WrongAttributes(topic);
|
||||
|
||||
try {
|
||||
new HelpFile(helpLocation, html);
|
||||
fail("Parsing did not fail for invalid stylesheet");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// good
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommentGetsIgnored() throws Exception {
|
||||
|
||||
Path helpDir = createTempHelpDir();
|
||||
addRequiredHelpDirStructure(helpDir);
|
||||
Path topic = createFakeHelpTopic(helpDir);
|
||||
DirectoryHelpModuleLocation helpLocation =
|
||||
new DirectoryHelpModuleLocation(helpDir.toFile());
|
||||
|
||||
Path html = createGoodHTMLFile_InvalidAnchor_CommentedOut_MultiLineComment(topic);
|
||||
HelpFile helpFile = new HelpFile(helpLocation, html);
|
||||
Collection<HREF> hrefs = helpFile.getAllHREFs();
|
||||
assertTrue(hrefs.isEmpty());
|
||||
}
|
||||
|
||||
// @Test
|
||||
// for debugging a real help file
|
||||
public void test() throws Exception {
|
||||
|
||||
Path path = Paths.get("<home dir>/<git>/ghidra/Ghidra/Features/" +
|
||||
"Base/src/main/help/help/topics/Annotations/Annotations.html");
|
||||
|
||||
Path helpDir = createTempHelpDir();
|
||||
addRequiredHelpDirStructure(helpDir);
|
||||
DirectoryHelpModuleLocation helpLocation =
|
||||
new DirectoryHelpModuleLocation(helpDir.toFile());
|
||||
AnchorManager anchorManager = new AnchorManager();
|
||||
ReferenceTagProcessor tagProcessor = new ReferenceTagProcessor(helpLocation, anchorManager);
|
||||
HTMLFileParser.scanHtmlFile(path, tagProcessor);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
|
||||
/** Has valid links */
|
||||
private Path createGoodHTMLFile(Path topic) throws IOException {
|
||||
String anchor = "ManagePluginsDialog";
|
||||
return createHelpContent(topic, anchor);
|
||||
}
|
||||
|
||||
private Path createBadHTMLFile_InvalidAnchor_WrongAttributes(Path topic) throws IOException {
|
||||
Path htmlPath = topic.resolve("FakeHTML_WrongAttributes.html");
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
String badAttr = "bob=1";
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/Frontpage.css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
"<BODY>\n" +
|
||||
"<H1><A name=\"ManagePluginsDialog\"></A>Configure Tool</H1>\n" +
|
||||
"Some text with reference to shared image <a "+badAttr+">Click me</a>\n" +
|
||||
"\n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
private Path createBadHTMLFile_InvalidIMG_WrongAttributes(Path topic) throws IOException {
|
||||
Path htmlPath = topic.resolve("FakeHTML_WrongAttributes.html");
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
String badAttr = "bob=1";
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/Frontpage.css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
"<BODY>\n" +
|
||||
"<H1><A name=\"ManagePluginsDialog\"></A>Configure Tool</H1>\n" +
|
||||
"Some text with reference to shared image <IMG "+badAttr+"s>\n" +
|
||||
"\n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
private Path createBadHTMLFile_InvalidAnchor_BadURI(Path topic) throws IOException {
|
||||
Path htmlPath = topic.resolve("FakeHTML_BadURI.html");
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
String badURI = ":baduri"; // no scheme name on this URI
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/Frontpage.css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
"<BODY>\n" +
|
||||
"<H1><A name=\"ManagePluginsDialog\"></A>Configure Tool</H1>\n" +
|
||||
"Some text with reference to shared image <a href=\""+badURI+"\">Click me</a>\n" +
|
||||
"\n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
private Path createBadHTMLFile_InvalidStyleSheet(Path topic) throws IOException {
|
||||
Path htmlPath = topic.resolve("FakeHTML_InvalidStyleSheet.html");
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
String badName = "bad_name";
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/"+badName+".css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
"<BODY>\n" +
|
||||
"<H1><A name=\"ManagePluginsDialog\"></A>Configure Tool</H1>\n" +
|
||||
"Some text with reference to shared image <IMG src=\"../../shared/test.png\">\n" +
|
||||
"\n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
|
||||
private Path createGoodHTMLFile_InvalidAnchor_CommentedOut_MultiLineComment(Path topic)
|
||||
throws IOException {
|
||||
Path htmlPath = topic.resolve("HTMLWithComment.html");
|
||||
Path file = Files.createFile(htmlPath);
|
||||
|
||||
String badURI = ":baduri"; // no scheme name on this URI
|
||||
|
||||
//@formatter:off
|
||||
String HTML =
|
||||
"<HTML>\n" +
|
||||
"<HEAD>\n" +
|
||||
"<TITLE>Configure Tool</TITLE>\n" +
|
||||
"<LINK rel=\"stylesheet\" type=\"text/css\" href=\"../../shared/Frontpage.css\">\n" +
|
||||
"</HEAD>\n" +
|
||||
"<BODY>\n" +
|
||||
"<H1><A name=\"ManagePluginsDialog\"></A>Configure Tool</H1>\n" +
|
||||
" <!--" +
|
||||
" Some text with reference to shared image <a href=\""+badURI+"\">Click me</a>\n" +
|
||||
" -->" +
|
||||
"\n" +
|
||||
"</BODY>\n" +
|
||||
"</HTML>\n";
|
||||
//@formatter:on
|
||||
|
||||
Files.write(file, HTML.getBytes(), StandardOpenOption.CREATE);
|
||||
return file;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* 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 ghidra.app.util.headless;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Locale;
|
||||
|
||||
import sun.java2d.HeadlessGraphicsEnvironment;
|
||||
|
||||
public class MyHeadlessGraphicsEnvironment extends GraphicsEnvironment {
|
||||
|
||||
static volatile boolean swingErrorRegistered = false;
|
||||
private static String preferredGraphicsEnv;
|
||||
|
||||
private GraphicsEnvironment localEnv;
|
||||
|
||||
static void setup() {
|
||||
//System.setProperty("java.awt.headless", "true");
|
||||
preferredGraphicsEnv = System.getProperty("java.awt.graphicsenv");
|
||||
System.setProperty("java.awt.graphicsenv", MyHeadlessGraphicsEnvironment.class.getName());
|
||||
}
|
||||
|
||||
public MyHeadlessGraphicsEnvironment() {
|
||||
swingErrorRegistered = true;
|
||||
try {
|
||||
throw new Exception("Swing invocation detected for Headless Mode");
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
getRealGraphicsEnvironemnt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics2D createGraphics(BufferedImage img) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Font[] getAllFonts() {
|
||||
return localEnv.getAllFonts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAvailableFontFamilyNames() {
|
||||
return localEnv.getAvailableFontFamilyNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAvailableFontFamilyNames(Locale l) {
|
||||
return localEnv.getAvailableFontFamilyNames(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsDevice getDefaultScreenDevice() throws HeadlessException {
|
||||
return localEnv.getDefaultScreenDevice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsDevice[] getScreenDevices() throws HeadlessException {
|
||||
return localEnv.getScreenDevices();
|
||||
}
|
||||
|
||||
private void getRealGraphicsEnvironemnt() {
|
||||
try {
|
||||
localEnv = (GraphicsEnvironment) Class.forName(preferredGraphicsEnv).newInstance();
|
||||
if (isHeadless()) {
|
||||
localEnv = new HeadlessGraphicsEnvironment(localEnv);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new Error("Could not find class: " + preferredGraphicsEnv);
|
||||
} catch (InstantiationException e) {
|
||||
throw new Error("Could not instantiate Graphics Environment: " + preferredGraphicsEnv);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new Error("Could not access Graphics Environment: " + preferredGraphicsEnv);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.app.util.headless;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Dialog.ModalExclusionType;
|
||||
import java.awt.Dialog.ModalityType;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.im.InputMethodHighlight;
|
||||
import java.awt.image.*;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import sun.awt.HeadlessToolkit;
|
||||
|
||||
public class MyHeadlessToolkit extends Toolkit {
|
||||
|
||||
static volatile boolean swingErrorRegistered = false;
|
||||
private static String preferredToolkit;
|
||||
|
||||
private Toolkit localToolKit;
|
||||
|
||||
static void setup() {
|
||||
//System.setProperty("java.awt.headless", "true");
|
||||
preferredToolkit = System.getProperty("awt.toolkit", "sun.awt.X11.XToolkit");
|
||||
System.setProperty("awt.toolkit", MyHeadlessToolkit.class.getName());
|
||||
}
|
||||
|
||||
public MyHeadlessToolkit() {
|
||||
swingErrorRegistered = true;
|
||||
try {
|
||||
throw new Exception("Swing invocation detected for Headless Mode");
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
getRealToolkit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beep() {
|
||||
localToolKit.beep();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkImage(Image image, int width, int height,
|
||||
ImageObserver observer) {
|
||||
return localToolKit.checkImage(image, width, height, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createImage(String filename) {
|
||||
return localToolKit.createImage(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createImage(URL url) {
|
||||
return localToolKit.createImage(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createImage(ImageProducer producer) {
|
||||
return localToolKit.createImage(producer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createImage(byte[] imagedata, int imageoffset, int imagelength) {
|
||||
return localToolKit.createImage(imagedata, imageoffset, imagelength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel() throws HeadlessException {
|
||||
return localToolKit.getColorModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getFontList() {
|
||||
return localToolKit.getFontList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics(Font font) {
|
||||
return localToolKit.getFontMetrics(font);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage(String filename) {
|
||||
return localToolKit.getImage(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage(URL url) {
|
||||
return localToolKit.getImage(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) {
|
||||
return localToolKit.getPrintJob(frame, jobtitle, props);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScreenResolution() throws HeadlessException {
|
||||
return localToolKit.getScreenResolution();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getScreenSize() throws HeadlessException {
|
||||
return localToolKit.getScreenSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getSystemClipboard() throws HeadlessException {
|
||||
return localToolKit.getSystemClipboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EventQueue getSystemEventQueueImpl() {
|
||||
return localToolKit.getSystemEventQueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModalExclusionTypeSupported(
|
||||
ModalExclusionType modalExclusionType) {
|
||||
return localToolKit.isModalExclusionTypeSupported(modalExclusionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModalityTypeSupported(ModalityType modalityType) {
|
||||
return localToolKit.isModalityTypeSupported(modalityType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TextAttribute, ?> mapInputMethodHighlight(
|
||||
InputMethodHighlight highlight) throws HeadlessException {
|
||||
return localToolKit.mapInputMethodHighlight(highlight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prepareImage(Image image, int width, int height,
|
||||
ImageObserver observer) {
|
||||
return localToolKit.prepareImage(image, width, height, observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync() {
|
||||
localToolKit.sync();
|
||||
}
|
||||
|
||||
private void getRealToolkit() {
|
||||
try {
|
||||
// We disable the JIT during toolkit initialization. This
|
||||
// tends to touch lots of classes that aren't needed again
|
||||
// later and therefore JITing is counter-productiive.
|
||||
java.lang.Compiler.disable();
|
||||
|
||||
Class<?> cls = null;
|
||||
try {
|
||||
try {
|
||||
cls = Class.forName(preferredToolkit);
|
||||
} catch (ClassNotFoundException ee) {
|
||||
throw new AWTError("Toolkit not found: " + preferredToolkit);
|
||||
}
|
||||
if (cls != null) {
|
||||
localToolKit = (Toolkit)cls.newInstance();
|
||||
if (GraphicsEnvironment.isHeadless()) {
|
||||
localToolKit = new HeadlessToolkit(localToolKit);
|
||||
}
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
throw new AWTError("Could not instantiate Toolkit: " + preferredToolkit);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AWTError("Could not access Toolkit: " + preferredToolkit);
|
||||
}
|
||||
|
||||
} finally {
|
||||
// Make sure to always re-enable the JIT.
|
||||
java.lang.Compiler.enable();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,313 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.framework.plugintool.testplugins.*;
|
||||
import ghidra.framework.plugintool.util.PluginException;
|
||||
import ghidra.framework.plugintool.util.PluginUtils;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
public class PluginManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private TestEnv env;
|
||||
private PluginTool tool;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
env = new TestEnv();
|
||||
tool = env.getTool();
|
||||
runSwing(() -> tool.setConfigChanged(false));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
env.dispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConflictPluginNames() {
|
||||
// Test loading a plugin that has a name conflict with another plugin
|
||||
try {
|
||||
tool.addPlugin(NameConflictingPlugin.class.getName());
|
||||
fail("Should have gotten a plugin exception because of the conflicting plugin names");
|
||||
}
|
||||
catch (PluginException e) {
|
||||
// ensure that the exception message mentions both of the conflicting plugin class names.
|
||||
String msg = e.getMessage();
|
||||
assertTrue(msg.contains(NameConflictingPlugin.class.getName()));
|
||||
assertTrue(msg.contains(
|
||||
ghidra.framework.plugintool.testplugins.secondconflict.NameConflictingPlugin.class.getName()));
|
||||
}
|
||||
assertNotPlugin(NameConflictingPlugin.class);
|
||||
assertNotPlugin(
|
||||
ghidra.framework.plugintool.testplugins.secondconflict.NameConflictingPlugin.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiamond() throws PluginException {
|
||||
// Test loading a plugin (A) that has dependencies in a diamond shape.
|
||||
// A
|
||||
// / \
|
||||
// B C
|
||||
// \ /
|
||||
// D
|
||||
tool.addPlugin(DiamondPluginA.class.getName());
|
||||
|
||||
assertPlugin(DiamondPluginA.class);
|
||||
assertPlugin(DiamondPluginB.class);
|
||||
assertPlugin(DiamondPluginC.class);
|
||||
assertPlugin(DiamondPluginD.class);
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCircularDependency() throws PluginException {
|
||||
// Test loading plugins that have circular dependencies.
|
||||
// Currently this is allowed but a warning is logged to the message console.
|
||||
// +---------+
|
||||
// | |
|
||||
// v |
|
||||
// A ------> B
|
||||
tool.addPlugin(CircularPluginA.class.getName());
|
||||
|
||||
assertPlugin(CircularPluginA.class);
|
||||
assertPlugin(CircularPluginB.class);
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
|
||||
removePlugin(getPlugin(CircularPluginB.class), false);
|
||||
|
||||
assertNotPlugin(CircularPluginA.class);
|
||||
assertNotPlugin(CircularPluginB.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadSameMultipleTimes() throws PluginException {
|
||||
// Loading the same plugin multiple times should not cause a problem and the second
|
||||
// attempt should just be ignored.
|
||||
tool.addPlugin(DiamondPluginD.class.getName());
|
||||
assertPlugin(DiamondPluginD.class);
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
|
||||
tool.addPlugin(DiamondPluginD.class.getName());
|
||||
// as long as we didn't get an exception everything is good
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingDependency() throws PluginException {
|
||||
// Test loading a plugin that has an dependency without a default provider.
|
||||
int pluginCount = tool.getManagedPlugins().size();
|
||||
try {
|
||||
tool.addPlugin(MissingDepPluginA.class.getName());
|
||||
fail("PluginA should have failed to load");
|
||||
}
|
||||
catch (PluginException e) {
|
||||
String msg = e.getMessage();
|
||||
assertTrue(msg.contains("Unresolved dependency") &&
|
||||
msg.contains(MissingDepServiceB.class.getName()));
|
||||
}
|
||||
assertEquals(pluginCount, tool.getManagedPlugins().size());
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
|
||||
// If we manually add the missing dependency, it should now work
|
||||
tool.addPlugin(MissingDepPluginB.class.getName());
|
||||
tool.addPlugin(MissingDepPluginA.class.getName());
|
||||
|
||||
assertPlugin(MissingDepPluginB.class);
|
||||
assertPlugin(MissingDepPluginA.class);
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadingDepSimultaneously() throws PluginException {
|
||||
// Load a plugin and a second plugin that provides a dependency at the same time.
|
||||
// Loading PluginA by itself would fail.
|
||||
tool.addPlugins(
|
||||
new String[] { MissingDepPluginA.class.getName(), MissingDepPluginB.class.getName() });
|
||||
|
||||
assertPlugin(MissingDepPluginA.class);
|
||||
assertPlugin(MissingDepPluginB.class);
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitFail() {
|
||||
// Test that a plugin that throws an error during init() is removed and cleaned up.
|
||||
int pluginCount = tool.getManagedPlugins().size();
|
||||
int disposeCountB = InitFailPluginB.disposeCount;
|
||||
|
||||
setErrorsExpected(true);
|
||||
try {
|
||||
tool.addPlugin(InitFailPluginB.class.getName());
|
||||
fail(
|
||||
"PluginB should have failed to load because PluginB throws exception during init()");
|
||||
}
|
||||
catch (PluginException pe) {
|
||||
// good
|
||||
assertTrue(pe.getMessage().contains(InitFailPluginB.ERROR_MSG));
|
||||
}
|
||||
setErrorsExpected(false);
|
||||
|
||||
assertEquals(disposeCountB + 1, InitFailPluginB.disposeCount);
|
||||
assertEquals(pluginCount, tool.getManagedPlugins().size());
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitFailInDependency() {
|
||||
// Test that a plugin that has a dependency that throws an error during init()
|
||||
// is removed and cleaned up.
|
||||
int pluginCount = tool.getManagedPlugins().size();
|
||||
int disposeCountA = InitFailPluginA.disposeCount;
|
||||
int disposeCountB = InitFailPluginB.disposeCount;
|
||||
|
||||
setErrorsExpected(true);
|
||||
try {
|
||||
tool.addPlugin(InitFailPluginA.class.getName());
|
||||
fail(
|
||||
"PluginA should have failed to load because PluginB throws exception during init()");
|
||||
}
|
||||
catch (PluginException pe) {
|
||||
// good
|
||||
assertTrue(pe.getMessage().contains(InitFailPluginB.ERROR_MSG));
|
||||
}
|
||||
setErrorsExpected(false);
|
||||
|
||||
assertNotPlugin(InitFailPluginA.class);
|
||||
assertEquals(pluginCount, tool.getManagedPlugins().size());
|
||||
assertEquals(disposeCountB + 1, InitFailPluginB.disposeCount);
|
||||
assertEquals(disposeCountA + 1, InitFailPluginA.disposeCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisposeFail() throws PluginException {
|
||||
// Test when a plugin throws an exception during its dispose()
|
||||
// Exceptions are logged to the console because the dispose was executed
|
||||
// on the swing thread.
|
||||
tool.addPlugin(DisposeFailPluginA.class.getName());
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
Plugin pluginA = getPlugin(DisposeFailPluginA.class);
|
||||
|
||||
runSwing(() -> tool.setConfigChanged(false));
|
||||
|
||||
removePlugin(pluginA, true);
|
||||
|
||||
assertNotPlugin(DisposeFailPluginA.class);
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadFailure_Isolated() {
|
||||
// test loading multiple plugins, good should load successfully, bad ones
|
||||
// shouldn't cause entire failure.
|
||||
|
||||
setErrorsExpected(true);
|
||||
try {
|
||||
tool.addPlugins(new String[] { IsolatedFailPluginA.class.getName(),
|
||||
IsolatedFailPluginB.class.getName() });
|
||||
fail("Should have gotten an exception because PluginB was bad");
|
||||
}
|
||||
catch (PluginException pe) {
|
||||
// currently expected behavior, partial errors cause exception
|
||||
}
|
||||
setErrorsExpected(false);
|
||||
|
||||
assertTrue(tool.hasConfigChanged());
|
||||
assertPlugin(IsolatedFailPluginA.class);
|
||||
assertNotPlugin(IsolatedFailPluginB.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniquePluginNames() {
|
||||
// Ensure all current plugins have a unique name.
|
||||
// Build a string with a list of the bad plugins and report it at the end.
|
||||
|
||||
Map<String, Class<? extends Plugin>> simpleNameToClassMap = new HashMap<>();
|
||||
Map<String, Set<Class<? extends Plugin>>> badPlugins = new HashMap<>();
|
||||
|
||||
for (Class<? extends Plugin> pluginClass : ClassSearcher.getClasses(Plugin.class)) {
|
||||
if (TestingPlugin.class.isAssignableFrom(pluginClass)) {
|
||||
// ignore plugins marked with the TestingPlugin interface because
|
||||
// they are supposed to have name conflicts and other problems.
|
||||
continue;
|
||||
}
|
||||
String pluginName = PluginUtils.getPluginNameFromClass(pluginClass);
|
||||
Class<? extends Plugin> previousPluginClass =
|
||||
simpleNameToClassMap.putIfAbsent(pluginName, pluginClass);
|
||||
if (previousPluginClass != null) {
|
||||
Set<Class<? extends Plugin>> set =
|
||||
badPlugins.computeIfAbsent(pluginName, x -> new HashSet<>());
|
||||
set.add(pluginClass);
|
||||
set.add(previousPluginClass);
|
||||
}
|
||||
}
|
||||
|
||||
// simplename: pluginclassname1,pluginclassname2*\n[repeat].
|
||||
String badPluginsStr = badPlugins.entrySet().stream().map( //
|
||||
entry -> entry.getKey() + ": " +
|
||||
entry.getValue().stream().map(pc -> pc.getName()).collect(Collectors.joining(",")) //
|
||||
).collect(Collectors.joining("\n"));
|
||||
|
||||
assertTrue("Plugins with name collisions: " + badPluginsStr, badPluginsStr.isEmpty());
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
|
||||
private void removePlugin(Plugin p, boolean exceptional) {
|
||||
|
||||
runSwing(() -> {
|
||||
try {
|
||||
|
||||
tool.removePlugins(new Plugin[] { p });
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (!exceptional) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void assertPlugin(Class<? extends Plugin> pluginClass) {
|
||||
assertTrue("Plugin " + pluginClass.getName() + " not present",
|
||||
tool.getManagedPlugins().stream().anyMatch(p -> p.getClass() == pluginClass));
|
||||
}
|
||||
|
||||
private void assertNotPlugin(Class<? extends Plugin> pluginClass) {
|
||||
|
||||
List<Plugin> plugins = tool.getManagedPlugins();
|
||||
for (Plugin p : plugins) {
|
||||
assertNotSame("Plugin " + pluginClass.getName() + " loaded but shouldn't be",
|
||||
p.getClass(), pluginClass);
|
||||
}
|
||||
}
|
||||
|
||||
private Plugin getPlugin(Class<? extends Plugin> pluginClass) {
|
||||
return tool.getManagedPlugins().stream().filter(
|
||||
p -> p.getClass() == pluginClass).findFirst().get();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool;
|
||||
|
||||
/**
|
||||
* Marker interface to signal that the implementing class is a test plugin and should
|
||||
* not be considered as 'real'.
|
||||
*/
|
||||
public interface TestingPlugin {
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Plugin for circular dependency testing {@link PluginManagerTest#testCircularDependency()}
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesProvided = { CircularServiceA.class },
|
||||
servicesRequired = { CircularServiceB.class } )
|
||||
//@formatter:on
|
||||
public class CircularPluginA extends Plugin implements CircularServiceA, TestingPlugin {
|
||||
|
||||
public CircularPluginA(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Plugin for circular dependency testing {@link PluginManagerTest#testCircularDependency()}
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesProvided = CircularServiceB.class,
|
||||
servicesRequired = CircularServiceA.class)
|
||||
//@formatter:on
|
||||
public class CircularPluginB extends Plugin implements CircularServiceB, TestingPlugin {
|
||||
|
||||
public CircularPluginB(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.framework.plugintool.PluginManagerTest;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* Plugin service for circular dependency testing {@link PluginManagerTest#testCircularDependency()}
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = CircularPluginA.class, description = "Test service")
|
||||
public interface CircularServiceA {
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.framework.plugintool.PluginManagerTest;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* Plugin service for circular dependency testing {@link PluginManagerTest#testCircularDependency()}
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = CircularPluginB.class, description = "Test service")
|
||||
public interface CircularServiceB {
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testDiamond()}
|
||||
* <pre>
|
||||
* A <------- you are here
|
||||
* / \
|
||||
* B C
|
||||
* \ /
|
||||
* D
|
||||
* </pre>
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesRequired = { DiamondServiceB.class, DiamondServiceC.class} )
|
||||
//@formatter:on
|
||||
public class DiamondPluginA extends Plugin implements TestingPlugin {
|
||||
|
||||
public DiamondPluginA(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testDiamond()}
|
||||
* <pre>
|
||||
* A
|
||||
* / \
|
||||
* B <---C--------------- you are here
|
||||
* \ /
|
||||
* D
|
||||
* </pre>
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesProvided = DiamondServiceB.class,
|
||||
servicesRequired = DiamondServiceD.class)
|
||||
//@formatter:on
|
||||
public class DiamondPluginB extends Plugin implements DiamondServiceB, TestingPlugin {
|
||||
|
||||
public DiamondPluginB(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testDiamond()}
|
||||
* <pre>
|
||||
* A
|
||||
* / \
|
||||
* B C <------ you are here
|
||||
* \ /
|
||||
* D
|
||||
* </pre>
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesProvided = DiamondServiceC.class,
|
||||
servicesRequired = DiamondServiceD.class)
|
||||
//@formatter:on
|
||||
public class DiamondPluginC extends Plugin implements DiamondServiceC, TestingPlugin {
|
||||
|
||||
public DiamondPluginC(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testDiamond()}
|
||||
* <pre>
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* \ /
|
||||
* D <--------- you are here
|
||||
* </pre>
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesProvided = DiamondServiceD.class)
|
||||
//@formatter:on
|
||||
public class DiamondPluginD extends Plugin implements DiamondServiceD, TestingPlugin {
|
||||
|
||||
public DiamondPluginD(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.framework.plugintool.PluginManagerTest;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* Test plugin service for {@link PluginManagerTest#testDiamond()}
|
||||
* <pre>
|
||||
* A
|
||||
* / \
|
||||
* B<----C------------ you are here
|
||||
* \ /
|
||||
* D
|
||||
* </pre>
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = DiamondPluginB.class, description = "Test service")
|
||||
public interface DiamondServiceB {
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.framework.plugintool.PluginManagerTest;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* Test plugin service for {@link PluginManagerTest#testDiamond()}
|
||||
* <pre>
|
||||
* A
|
||||
* / \
|
||||
* B C <---------- you are here
|
||||
* \ /
|
||||
* D
|
||||
* </pre>
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = DiamondPluginC.class, description = "Test service")
|
||||
public interface DiamondServiceC {
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.framework.plugintool.PluginManagerTest;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* Test plugin service for {@link PluginManagerTest#testDiamond()}
|
||||
* <pre>
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* \ /
|
||||
* D <---------- you are here
|
||||
* </pre>
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = DiamondPluginD.class, description = "Test service")
|
||||
public interface DiamondServiceD {
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testDisposeFail()} and friends.
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin" )
|
||||
//@formatter:on
|
||||
public class DisposeFailPluginA extends Plugin implements TestingPlugin {
|
||||
public static final String ERROR_MSG = "PluginA dispose exception message";
|
||||
public static int disposeCount = 0;
|
||||
|
||||
public DisposeFailPluginA(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispose() {
|
||||
throw new RuntimeException(ERROR_MSG);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testInitFail()} and friends.
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesRequired = { InitFailServiceB.class } )
|
||||
//@formatter:on
|
||||
public class InitFailPluginA extends Plugin implements TestingPlugin {
|
||||
public static int disposeCount = 0;
|
||||
|
||||
public InitFailPluginA(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispose() {
|
||||
disposeCount++;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testInitFail()} and friends.
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesProvided = { InitFailServiceB.class } )
|
||||
//@formatter:on
|
||||
public class InitFailPluginB extends Plugin implements InitFailServiceB, TestingPlugin {
|
||||
public static final String ERROR_MSG = "PluginB fails during Plugin.init()";
|
||||
public static int disposeCount = 0;
|
||||
|
||||
public InitFailPluginB(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
throw new RuntimeException(ERROR_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispose() {
|
||||
disposeCount++;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.framework.plugintool.PluginManagerTest;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* Test plugin service for {@link PluginManagerTest#testInitFail()} and friends.
|
||||
*/
|
||||
@ServiceInfo(defaultProvider = InitFailPluginB.class, description = "Test service")
|
||||
public interface InitFailServiceB {
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testLoadFailure_Isolated}
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin")
|
||||
//@formatter:on
|
||||
public class IsolatedFailPluginA extends Plugin implements TestingPlugin {
|
||||
|
||||
public IsolatedFailPluginA(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testLoadFailure_Isolated}
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin")
|
||||
//@formatter:on
|
||||
public class IsolatedFailPluginB extends Plugin implements TestingPlugin {
|
||||
|
||||
public static final String ERROR_MSG = "IsolatedFailPluginB error message";
|
||||
|
||||
public IsolatedFailPluginB(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
throw new RuntimeException(ERROR_MSG);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testMissingDependency()} and
|
||||
* {@link PluginManagerTest#testLoadingDepSimultaneously()}
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesRequired = { MissingDepServiceB.class } )
|
||||
//@formatter:on
|
||||
public class MissingDepPluginA extends Plugin implements TestingPlugin {
|
||||
|
||||
public MissingDepPluginA(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testMissingDependency()} and
|
||||
* {@link PluginManagerTest#testLoadingDepSimultaneously()}
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin",
|
||||
description = "Test plugin",
|
||||
servicesProvided = MissingDepServiceB.class)
|
||||
//@formatter:on
|
||||
public class MissingDepPluginB extends Plugin implements MissingDepServiceB, TestingPlugin {
|
||||
|
||||
public MissingDepPluginB(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.framework.plugintool.PluginManagerTest;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
|
||||
/**
|
||||
* Test plugin service for {@link PluginManagerTest#testMissingDependency()} and
|
||||
* {@link PluginManagerTest#testLoadingDepSimultaneously()}
|
||||
*/
|
||||
@ServiceInfo(description = "Test service" /*, defaultProvider=not_specified*/ )
|
||||
public interface MissingDepServiceB {
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
//@formatter:off
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testConflictPluginNames()}.
|
||||
*
|
||||
* Class name needs to match *Plugin so the class searcher finds it.
|
||||
*/
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin name collision",
|
||||
description = "Test plugin name collision.")
|
||||
//@formatter:on
|
||||
public class NameConflictingPlugin extends Plugin implements TestingPlugin {
|
||||
|
||||
public NameConflictingPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.framework.plugintool.testplugins.secondconflict;
|
||||
|
||||
import ghidra.app.DeveloperPluginPackage;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
|
||||
/**
|
||||
* Test plugin for {@link PluginManagerTest#testConflictPluginNames()}
|
||||
*
|
||||
* Class name needs to match *Plugin so the class searcher finds it.
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(status = PluginStatus.HIDDEN,
|
||||
packageName = DeveloperPluginPackage.NAME,
|
||||
category = PluginCategoryNames.UNMANAGED,
|
||||
shortDescription = "Test plugin name collision",
|
||||
description = "Test plugin name collision.")
|
||||
//@formatter:on
|
||||
public class NameConflictingPlugin extends Plugin implements TestingPlugin {
|
||||
|
||||
public NameConflictingPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,121 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.program.model.lang;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||
|
||||
public class RegisterValueContextTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||
|
||||
private Language language;
|
||||
|
||||
private Register regContext;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
LanguageService languageService = getLanguageService();
|
||||
language = languageService.getLanguage(new LanguageID("x86:LE:32:default"));
|
||||
|
||||
regContext = language.getContextBaseRegister();// 4-byte context reg
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterValueMask() {
|
||||
|
||||
RegisterValue val = new RegisterValue(regContext, BigInteger.valueOf(0x12345678));
|
||||
BigInteger value = val.getUnsignedValue();
|
||||
assertEquals(0x12345678, value.longValue());
|
||||
BigInteger valueMask = val.getValueMask();
|
||||
assertEquals(0xffffffffL, valueMask.longValue());
|
||||
|
||||
RegisterValue newValue = new RegisterValue(regContext, value, valueMask);
|
||||
assertEquals(0x12345678, newValue.getUnsignedValue().longValue());
|
||||
assertEquals(0xffffffffL, newValue.getValueMask().longValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytes() {
|
||||
|
||||
RegisterValue val = new RegisterValue(regContext,
|
||||
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 1, 2, 3, 4 });
|
||||
|
||||
assertEquals(0x01020304, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x01020304, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x01020304, val.getUnsignedValue().longValue());
|
||||
assertEquals(0x01020304, val.getSignedValue().longValue());
|
||||
assertEquals(0x0ffffffffL, val.getValueMask().longValue());
|
||||
|
||||
val = new RegisterValue(regContext,
|
||||
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xf0, (byte) 0xff, 1, 2, 3, 4 });
|
||||
|
||||
assertEquals(0x01020304, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x01020304, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(null, val.getUnsignedValue());
|
||||
assertEquals(null, val.getSignedValue());
|
||||
assertEquals(0x0fffff0ffL, val.getValueMask().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytesGrow() {
|
||||
|
||||
RegisterValue val =
|
||||
new RegisterValue(regContext, new byte[] { (byte) 0xff, (byte) 0xff, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x12340000, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x12340000, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(null, val.getUnsignedValue());
|
||||
assertEquals(null, val.getSignedValue());
|
||||
assertEquals(0x0ffff0000L, val.getValueMask().longValue());
|
||||
|
||||
val = new RegisterValue(regContext, new byte[] { (byte) 0x10, (byte) 0xff, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x10340000, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x10340000, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(null, val.getUnsignedValue());
|
||||
assertEquals(null, val.getSignedValue());
|
||||
assertEquals(0x10ff0000, val.getValueMask().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytesShrink() {
|
||||
|
||||
RegisterValue val = new RegisterValue(regContext, new byte[] { (byte) 0xff, (byte) 0xff,
|
||||
(byte) 0xff, (byte) 0xff, 0, 0, 0, 0, 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0 });
|
||||
|
||||
assertEquals(0x12345678, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x12345678, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x12345678, val.getUnsignedValue().longValue());
|
||||
assertEquals(0x12345678, val.getSignedValue().longValue());
|
||||
assertEquals(0x0ffffffffL, val.getValueMask().longValue());
|
||||
|
||||
val = new RegisterValue(regContext, new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xf0,
|
||||
(byte) 0xff, 0, 0, 0, 0, 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0 });
|
||||
|
||||
assertEquals(0x12345078, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x12345078, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(null, val.getUnsignedValue());
|
||||
assertEquals(null, val.getSignedValue());
|
||||
assertEquals(0x0fffff0ffL, val.getValueMask().longValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.program.model.lang;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
|
||||
|
||||
public class RegisterValueTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||
|
||||
private Language language;
|
||||
|
||||
private Register regEAX;
|
||||
private Register regAX;
|
||||
private Register regAH;
|
||||
private Register regAL;
|
||||
|
||||
private Register regEBX;
|
||||
private Register regBX;
|
||||
private Register regBH;
|
||||
private Register regBL;
|
||||
|
||||
private Register regCF;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
LanguageService languageService = getLanguageService();
|
||||
language = languageService.getLanguage(new LanguageID("x86:LE:32:default"));
|
||||
|
||||
regEAX = language.getRegister("EAX");// 4-byte reg within 8-byte parent
|
||||
regAX = language.getRegister("AX");
|
||||
regAH = language.getRegister("AH");
|
||||
regAL = language.getRegister("AL");
|
||||
|
||||
regEBX = language.getRegister("EBX");// 4-byte reg within 8-byte parent
|
||||
regBX = language.getRegister("BX");
|
||||
regBH = language.getRegister("BH");
|
||||
regBL = language.getRegister("BL");
|
||||
|
||||
regCF = language.getRegister("CF");// 1-byte reg (basereg)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterValueMask() {
|
||||
|
||||
RegisterValue valAH = new RegisterValue(regAH, BigInteger.valueOf(0x55));
|
||||
BigInteger value = valAH.getUnsignedValue();
|
||||
assertEquals(0x55, value.longValue());
|
||||
BigInteger valueMask = valAH.getValueMask();
|
||||
assertEquals(0xff, valueMask.longValue());
|
||||
|
||||
RegisterValue newValue = new RegisterValue(regBH, value, valueMask);
|
||||
assertEquals(0x55, newValue.getUnsignedValue().longValue());
|
||||
assertEquals(0xff, newValue.getValueMask().longValue());
|
||||
|
||||
newValue = newValue.getRegisterValue(regEBX);
|
||||
assertEquals(0x5500, newValue.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0xff00, newValue.getValueMask().longValue());
|
||||
|
||||
newValue = new RegisterValue(regBL, value, valueMask);
|
||||
assertEquals(0x55, newValue.getUnsignedValue().longValue());
|
||||
assertEquals(0xff, newValue.getValueMask().longValue());
|
||||
|
||||
RegisterValue valEAX = valAH.getRegisterValue(regEAX).assign(regAL, newValue);
|
||||
assertEquals(0x5555, valEAX.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0xffff, valEAX.getValueMask().longValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytes() {
|
||||
|
||||
RegisterValue val = new RegisterValue(regEBX,
|
||||
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
|
||||
(byte) 0xff, (byte) 0xff, (byte) 0xff, 0, 0, 0, 0, 0, 0, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x1234, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x1234, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x1234, val.getUnsignedValue().longValue());
|
||||
assertEquals(0x1234, val.getSignedValue().longValue());
|
||||
assertEquals(0x0ffffffffL, val.getValueMask().longValue());
|
||||
|
||||
val = new RegisterValue(regEBX,
|
||||
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
|
||||
(byte) 0xff, (byte) 0xf0, (byte) 0xff, 0, 0, 0, 0, 0, 0, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x1034, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x1034, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(null, val.getUnsignedValue());
|
||||
assertEquals(null, val.getSignedValue());
|
||||
assertEquals(0x0fffff0ffL, val.getValueMask().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytesGrow() {
|
||||
|
||||
RegisterValue val =
|
||||
new RegisterValue(regEBX, new byte[] { (byte) 0xff, (byte) 0xff, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x1234, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x1234, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x1234, val.getUnsignedValue().longValue());
|
||||
assertEquals(0x1234, val.getSignedValue().longValue());
|
||||
assertEquals(0x0ffffffffL, val.getValueMask().longValue());
|
||||
|
||||
val = new RegisterValue(regEBX, new byte[] { (byte) 0x10, (byte) 0xff, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x1034, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x1034, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(null, val.getUnsignedValue());
|
||||
assertEquals(null, val.getSignedValue());
|
||||
assertEquals(0x10ff, val.getValueMask().longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytesShrink() {
|
||||
|
||||
RegisterValue val =
|
||||
new RegisterValue(regCF, new byte[] { (byte) 0xff, (byte) 0xff, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x34, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x34, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x34, val.getUnsignedValue().longValue());
|
||||
assertEquals(0x34, val.getSignedValue().longValue());
|
||||
assertEquals(0x0ffL, val.getValueMask().longValue());
|
||||
|
||||
val = new RegisterValue(regCF, new byte[] { (byte) 0xf0, (byte) 0xff, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x34, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x34, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x34, val.getUnsignedValue().longValue());
|
||||
assertEquals(0x34, val.getSignedValue().longValue());
|
||||
assertEquals(0x0ffL, val.getValueMask().longValue());
|
||||
|
||||
val = new RegisterValue(regCF, new byte[] { (byte) 0xff, (byte) 0xf0, 0x12, 0x34 });
|
||||
|
||||
assertEquals(0x30, val.getUnsignedValueIgnoreMask().longValue());
|
||||
assertEquals(0x30, val.getSignedValueIgnoreMask().longValue());
|
||||
assertEquals(null, val.getUnsignedValue());
|
||||
assertEquals(null, val.getSignedValue());
|
||||
assertEquals(0x0f0, val.getValueMask().longValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,428 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.server;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import db.*;
|
||||
import db.buffers.BufferFile;
|
||||
import db.buffers.ManagedBufferFile;
|
||||
import ghidra.framework.client.ClientUtil;
|
||||
import ghidra.framework.store.*;
|
||||
import ghidra.framework.store.local.LocalFileSystem;
|
||||
import ghidra.server.store.RepositoryFile;
|
||||
import ghidra.server.store.RepositoryFolder;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.FileInUseException;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
public class RepositoryFileSystemTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private static final String USER = ClientUtil.getUserName();
|
||||
|
||||
private File serverRoot;
|
||||
|
||||
private RepositoryManager mgr;
|
||||
private Repository repository;
|
||||
|
||||
private List<MyEvent> events = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
File parent = createTempDirectory(getClass().getSimpleName());
|
||||
|
||||
// Create server instance
|
||||
serverRoot = new File(parent, "My_Server");
|
||||
FileUtilities.deleteDir(serverRoot);
|
||||
serverRoot.mkdir();
|
||||
|
||||
mgr = new RepositoryManager(serverRoot, false, false, 0, false);
|
||||
mgr.getUserManager().addUser(USER);
|
||||
|
||||
repository = mgr.createRepository(USER, "My_Repository");
|
||||
|
||||
LocalFileSystem fs = (LocalFileSystem) getInstanceField("fileSystem", repository);
|
||||
fs.addFileSystemListener(new MyFileSystemListener());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mgr != null) {
|
||||
mgr.dispose();
|
||||
}
|
||||
FileUtilities.deleteDir(serverRoot);
|
||||
}
|
||||
|
||||
private RepositoryFile createDatabase(String parentPath, String itemName, int maxVersion)
|
||||
throws Exception {
|
||||
|
||||
RepositoryFolder folder = repository.getFolder(USER, parentPath, true);
|
||||
|
||||
DBHandle dbh = new DBHandle();
|
||||
long id = dbh.startTransaction();
|
||||
Schema schema =
|
||||
new Schema(0, "key", new Class[] { IntField.class }, new String[] { "dummy" });
|
||||
dbh.createTable("test", schema);
|
||||
dbh.endTransaction(id, true);
|
||||
ManagedBufferFile bf = folder.createDatabase(itemName, FileIDFactory.createFileID(),
|
||||
dbh.getBufferSize(), "Database", USER, null);
|
||||
bf.setVersionComment("Version 1");
|
||||
dbh.saveAs(bf, true, null);
|
||||
long checkoutId = bf.getCheckinID();
|
||||
assertNotNull(dbh.getTable("test"));
|
||||
dbh.close();
|
||||
|
||||
RepositoryFile file = folder.getFile(itemName);
|
||||
assertNotNull(file);
|
||||
assertEquals(1, file.getItem().getVersion());
|
||||
|
||||
for (int i = 2; i <= maxVersion; i++) {
|
||||
|
||||
// Checkout and open for update
|
||||
bf = file.openDatabase(checkoutId, USER);
|
||||
dbh = new DBHandle(bf);
|
||||
assertTrue(dbh.canUpdate());
|
||||
Table testTable = dbh.getTable("test");
|
||||
assertEquals(i - 2, testTable.getRecordCount());
|
||||
|
||||
// Verify that update is not permitted for second open
|
||||
BufferFile bf2 = file.openDatabase(1, -1, USER);
|
||||
DBHandle dbh2 = new DBHandle(bf2);
|
||||
assertTrue(!dbh2.canUpdate());
|
||||
assertNotNull(dbh2.getTable("test"));
|
||||
dbh2.close();
|
||||
|
||||
// Add record
|
||||
long txId = dbh.startTransaction();
|
||||
Record rec = schema.createRecord(i);
|
||||
rec.setIntValue(0, i);
|
||||
testTable.putRecord(rec);
|
||||
Msg.debug(this, "Added record to test table, key=" + i);
|
||||
Msg.debug(this,
|
||||
"Added record to Record count for test table: " + testTable.getRecordCount());
|
||||
dbh.endTransaction(txId, true);
|
||||
|
||||
// Create new version
|
||||
Msg.debug(this, "Saving database version " + i);
|
||||
dbh.save("Version " + i, new MyChangeSet(), null);
|
||||
dbh.close();
|
||||
|
||||
// Verify item current version
|
||||
assertEquals(i, file.getItem().getVersion());
|
||||
|
||||
// Check version history
|
||||
Version[] versions = file.getVersions(USER);
|
||||
assertEquals(i, versions.length);
|
||||
for (int n = 0; n < i; n++) {
|
||||
assertEquals(n + 1, versions[n].getVersion());
|
||||
assertEquals("Version " + (n + 1), versions[n].getComment());
|
||||
assertEquals(USER, versions[n].getUser());
|
||||
}
|
||||
|
||||
}
|
||||
file.terminateCheckout(checkoutId, USER, false);
|
||||
return file;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteDataBaseVersions() {
|
||||
try {
|
||||
RepositoryFolder rootFolder = repository.getFolder(USER, "/", true);
|
||||
RepositoryFolder[] folders = rootFolder.getFolders();
|
||||
assertNotNull(folders);
|
||||
assertEquals(0, folders.length);
|
||||
|
||||
RepositoryFile file = createDatabase("/abc", "fred", 3);
|
||||
|
||||
RepositoryFolder folder = repository.getFolder(USER, "/abc", false);
|
||||
assertNotNull(folder);
|
||||
|
||||
// Can't delete open version
|
||||
// BufferFile bf = item.open((int)1);
|
||||
// try {
|
||||
// item.delete(1);
|
||||
// fail();
|
||||
// } catch (FileInUseException e) {
|
||||
// // expected
|
||||
// }
|
||||
// finally {
|
||||
// bf.close();
|
||||
// }
|
||||
|
||||
// Can't delete checked-out version
|
||||
ItemCheckoutStatus coStatus = file.checkout(CheckoutType.NORMAL, USER, null);
|
||||
try {
|
||||
file.delete(3, USER);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (FileInUseException e) {
|
||||
// expected
|
||||
}
|
||||
file = folder.getFile("fred");
|
||||
assertNotNull(file);
|
||||
|
||||
// delete oldest version
|
||||
file.delete(1, USER);
|
||||
Thread.sleep(50);
|
||||
file = folder.getFile("fred");
|
||||
assertNotNull(file);
|
||||
|
||||
// verify that version 2 and 3 are still available
|
||||
assertEquals(3, file.getItem().getVersion());
|
||||
Version[] versions = file.getVersions(USER);
|
||||
assertEquals(2, versions.length);
|
||||
assertEquals(2, versions[0].getVersion());
|
||||
assertEquals(3, versions[1].getVersion());
|
||||
|
||||
file.terminateCheckout(coStatus.getCheckoutId(), USER, false);
|
||||
Thread.sleep(50);
|
||||
|
||||
// delete current version
|
||||
file.delete(3, USER);
|
||||
Thread.sleep(50);
|
||||
file = folder.getFile("fred");
|
||||
assertNotNull(file);
|
||||
|
||||
// verify that version 2 is still available
|
||||
assertEquals(2, file.getItem().getVersion());
|
||||
versions = file.getVersions(USER);
|
||||
assertEquals(1, versions.length);
|
||||
assertEquals(2, versions[0].getVersion());
|
||||
|
||||
// Open version 2 for check
|
||||
DBHandle dbh = new DBHandle(file.openDatabase(2, -1, USER));
|
||||
try {
|
||||
Table testTable = dbh.getTable("test");
|
||||
assertEquals(1, testTable.getRecordCount());
|
||||
Record rec = testTable.getRecord(2);
|
||||
assertNotNull(rec);
|
||||
assertEquals(2, rec.getIntValue(0));
|
||||
}
|
||||
finally {
|
||||
dbh.close();
|
||||
}
|
||||
|
||||
// delete last version
|
||||
file.delete(2, USER);
|
||||
Thread.sleep(50);
|
||||
file = folder.getFile("fred");
|
||||
assertNull(file);
|
||||
|
||||
folders = rootFolder.getFolders();
|
||||
assertNotNull(folders);
|
||||
assertEquals(0, folders.length);
|
||||
|
||||
Thread.sleep(500);// wait for events
|
||||
|
||||
assertEquals(8, events.size());
|
||||
checkEvent("Folder Created", "/", "abc", null, null, events.get(0));
|
||||
checkEvent("Item Created", "/abc", "fred", null, null, events.get(1));
|
||||
checkEvent("Item Changed", "/abc", "fred", null, null, events.get(2));// version 2 created
|
||||
checkEvent("Item Changed", "/abc", "fred", null, null, events.get(3));// version 3 created
|
||||
checkEvent("Item Changed", "/abc", "fred", null, null, events.get(4));// version 1 deleted
|
||||
checkEvent("Item Changed", "/abc", "fred", null, null, events.get(5));// version 3 deleted
|
||||
checkEvent("Item Deleted", "/abc", "fred", null, null, events.get(6));// last version deleted
|
||||
checkEvent("Folder Deleted", "/", "abc", null, null, events.get(7));
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkEvent(String op, String path, String name, String newPath, String newName,
|
||||
Object evObj) {
|
||||
MyEvent event = (MyEvent) evObj;
|
||||
MyEvent ev = new MyEvent(op, path, name, newPath, newName);
|
||||
assertEquals(ev, event);
|
||||
}
|
||||
|
||||
class MyChangeSet implements DBChangeSet {
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#read(ghidra.framework.store.db.DBHandle)
|
||||
*/
|
||||
@Override
|
||||
public void read(DBHandle dbh) throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#write(ghidra.framework.store.db.DBHandle)
|
||||
*/
|
||||
@Override
|
||||
public void write(DBHandle dbh, boolean isRecoverSave) throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#clear()
|
||||
*/
|
||||
public void clear() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#undo()
|
||||
*/
|
||||
public void undo() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#redo()
|
||||
*/
|
||||
public void redo() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#setMaxUndos(int)
|
||||
*/
|
||||
public void setMaxUndos(int maxUndos) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#clearUndo()
|
||||
*/
|
||||
public void clearUndo() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#startTransaction()
|
||||
*/
|
||||
public void startTransaction() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see ghidra.framework.model.ChangeSet#endTransaction(boolean)
|
||||
*/
|
||||
public void endTransaction(boolean commit) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyFileSystemListener implements FileSystemListener {
|
||||
@Override
|
||||
public void folderCreated(String parentPath, String name) {
|
||||
events.add(new MyEvent("Folder Created", parentPath, name, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemCreated(String parentPath, String name) {
|
||||
events.add(new MyEvent("Item Created", parentPath, name, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void folderDeleted(String parentPath, String name) {
|
||||
events.add(new MyEvent("Folder Deleted", parentPath, name, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void folderMoved(String parentPath, String name, String newParentPath) {
|
||||
events.add(new MyEvent("Folder Moved", parentPath, name, newParentPath, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void folderRenamed(String parentPath, String oldFolderName, String newFolderName) {
|
||||
events.add(
|
||||
new MyEvent("Folder Renamed", parentPath, oldFolderName, null, newFolderName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemDeleted(String folderPath, String itemName) {
|
||||
events.add(new MyEvent("Item Deleted", folderPath, itemName, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemRenamed(String folderPath, String oldItemName, String newItemName) {
|
||||
events.add(new MyEvent("Item Renamed", folderPath, oldItemName, null, newItemName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemMoved(String parentPath, String name, String newParentPath,
|
||||
String newName) {
|
||||
events.add(new MyEvent("Item Moved", parentPath, name, newParentPath, newName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemChanged(String parentPath, String itemName) {
|
||||
events.add(new MyEvent("Item Changed", parentPath, itemName, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncronize() {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyEvent {
|
||||
String op;
|
||||
String parentPath;
|
||||
String name;
|
||||
String newParentPath;
|
||||
String newName;
|
||||
|
||||
MyEvent(String op, String parentPath, String name, String newParentPath, String newName) {
|
||||
this.op = op;
|
||||
this.parentPath = parentPath;
|
||||
this.name = name;
|
||||
this.newParentPath = newParentPath;
|
||||
this.newName = newName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
MyEvent other = (MyEvent) obj;
|
||||
return eq(op, other.op) && eq(parentPath, other.parentPath) && eq(name, other.name) &&
|
||||
eq(newParentPath, other.newParentPath) && eq(newName, other.newName);
|
||||
}
|
||||
|
||||
private boolean eq(String s1, String s2) {
|
||||
if (s1 == null) {
|
||||
return s2 == null;
|
||||
}
|
||||
return s1.equals(s2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return op + " " + parentPath + " " + name + " " + newParentPath + " " + newName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.framework.remote.User;
|
||||
import ghidra.server.remote.ServerTestUtil;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.util.exception.DuplicateFileException;
|
||||
import ghidra.util.exception.UserAccessException;
|
||||
|
||||
public class RepositoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private RepositoryManager mgr;
|
||||
private File root;
|
||||
|
||||
public RepositoryManagerTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
File parent = createTempDirectory(getName());
|
||||
root = new File(parent, "Repositories");
|
||||
if (root.exists()) {
|
||||
deleteFiles(root);
|
||||
root.delete();
|
||||
}
|
||||
root.mkdir();
|
||||
writeUserList(root);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (mgr != null) {
|
||||
mgr.dispose();
|
||||
}
|
||||
deleteFiles(root);
|
||||
root.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRepositoryManager() throws Exception {
|
||||
|
||||
mgr = new RepositoryManager(root, false, false, 0, false);
|
||||
assertNotNull(mgr);
|
||||
|
||||
String[] userNames = mgr.getAllUsers("User_0");
|
||||
assertEquals(10, userNames.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRepositoryManagerWithAnonymous() throws Exception {
|
||||
|
||||
mgr = new RepositoryManager(root, false, false, 0, true);
|
||||
assertNotNull(mgr);
|
||||
|
||||
String[] userNames = mgr.getAllUsers("User_0");
|
||||
assertEquals(10, userNames.length);
|
||||
|
||||
userNames = mgr.getAllUsers(UserManager.ANONYMOUS_USERNAME);
|
||||
assertEquals(0, userNames.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRepository() throws Exception {
|
||||
mgr = new RepositoryManager(root, false, false, 0, false);
|
||||
|
||||
Repository rep = mgr.createRepository("User_0", "REPOSITORY_A");
|
||||
assertNotNull(rep);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateRepositoryAnonymous() throws Exception {
|
||||
mgr = new RepositoryManager(root, false, false, 0, true);
|
||||
|
||||
Repository rep = mgr.createRepository("User_0", "REPOSITORY_A");
|
||||
assertNotNull(rep);
|
||||
|
||||
try {
|
||||
mgr.createRepository(UserManager.ANONYMOUS_USERNAME, "REPOSITORY_B");
|
||||
Assert.fail("Expected UserAccessException");
|
||||
}
|
||||
catch (UserAccessException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDuplicateRepository() throws Exception {
|
||||
mgr = new RepositoryManager(root, false, false, 0, false);
|
||||
mgr.createRepository("User_0", "REPOSITORY_A");
|
||||
try {
|
||||
mgr.createRepository("User_5", "REPOSITORY_A");
|
||||
Assert.fail("Should have gotten DuplicateNameException!");
|
||||
}
|
||||
catch (DuplicateFileException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRepository() throws Exception {
|
||||
mgr = new RepositoryManager(root, false, false, 0, true);
|
||||
Repository rep1 = mgr.createRepository("User_0", "REPOSITORY_A");
|
||||
addUsers("User_0", true, rep1);
|
||||
|
||||
Repository rep2 = mgr.createRepository("User_0", "REPOSITORY_B");
|
||||
addUsers("User_0", false, rep2);
|
||||
|
||||
Repository rep3 = mgr.createRepository("User_9", "REPOSITORY_9A");
|
||||
addUsers("User_9", false, rep3);
|
||||
|
||||
Repository rep4 = mgr.createRepository("User_9", "REPOSITORY_9B");
|
||||
addUsers("User_9", false, rep4);
|
||||
|
||||
assertEquals(rep1, mgr.getRepository("User_1", "REPOSITORY_A"));
|
||||
assertEquals(rep1, mgr.getRepository(UserManager.ANONYMOUS_USERNAME, "REPOSITORY_A"));
|
||||
assertEquals(rep2, mgr.getRepository("User_2", "REPOSITORY_B"));
|
||||
try {
|
||||
mgr.getRepository(UserManager.ANONYMOUS_USERNAME, "REPOSITORY_B");
|
||||
Assert.fail("Expected UserAccessException");
|
||||
}
|
||||
catch (UserAccessException e) {
|
||||
// expected
|
||||
}
|
||||
assertEquals(rep3, mgr.getRepository("User_3", "REPOSITORY_9A"));
|
||||
assertEquals(rep4, mgr.getRepository("User_4", "REPOSITORY_9B"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRepositoryBadUser() throws Exception {
|
||||
mgr = new RepositoryManager(root, false, false, 0, false);
|
||||
mgr.createRepository("User_0", "REPOSITORY_A");
|
||||
|
||||
try {
|
||||
mgr.getRepository("unknownUser", "REPOSITORY_A");
|
||||
Assert.fail("Should not have been able to get repository!");
|
||||
}
|
||||
catch (UserAccessException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
mgr.getRepository(UserManager.ANONYMOUS_USERNAME, "REPOSITORY_A");
|
||||
Assert.fail("Should not have been able to get repository!");
|
||||
}
|
||||
catch (UserAccessException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private void addUsers(String currentUser, boolean allowAnonymousAccess, Repository rep)
|
||||
throws Exception {
|
||||
User[] users = new User[10];
|
||||
for (int i = 0; i < 10; i++) {
|
||||
String name = "User_" + i;
|
||||
int type = User.READ_ONLY;
|
||||
if (name.equals(currentUser)) {
|
||||
type = User.ADMIN;
|
||||
}
|
||||
users[i] = new User("User_" + i, type);
|
||||
}
|
||||
rep.setUserList(currentUser, users, allowAnonymousAccess);
|
||||
}
|
||||
|
||||
private void writeUserList(File repositoryRoot) throws Exception {
|
||||
|
||||
String[] userNames = new String[10];
|
||||
for (int i = 0; i < userNames.length; i++) {
|
||||
userNames[i] = "User_" + i;
|
||||
}
|
||||
|
||||
ServerTestUtil.createUsers(repositoryRoot.getAbsolutePath(), userNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive method to delete files in the given parent directory.
|
||||
*/
|
||||
private boolean deleteFiles(File parent) {
|
||||
|
||||
File[] f = parent.listFiles();
|
||||
for (File element : f) {
|
||||
if (element.isDirectory()) {
|
||||
if (!deleteFiles(element)) {
|
||||
return false;
|
||||
}
|
||||
element.delete();
|
||||
}
|
||||
else if (!element.delete()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.framework.remote.User;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.util.NamingUtilities;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.UserAccessException;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
public class RepositoryTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private static final String REPOSITORY_NAME = "My_Repository";
|
||||
|
||||
private File serverRoot;
|
||||
private RepositoryManager mgr;
|
||||
private Repository repository;
|
||||
private String userName;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
userName = SystemUtilities.getUserName();
|
||||
|
||||
File parent = createTempDirectory(getClass().getSimpleName());
|
||||
|
||||
// Create repository manager with no users
|
||||
serverRoot = new File(parent, "My_Server");
|
||||
FileUtilities.deleteDir(serverRoot);
|
||||
serverRoot.mkdir();
|
||||
|
||||
mgr = new RepositoryManager(serverRoot, false, false, 0, false);
|
||||
mgr.getUserManager().addUser(userName);
|
||||
|
||||
repository = mgr.createRepository(userName, REPOSITORY_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRepositoryName() throws Exception {
|
||||
assertEquals(REPOSITORY_NAME, repository.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetGetUserList() throws Exception {
|
||||
User[] users = new User[5];
|
||||
users[0] = new User("user-a", User.READ_ONLY);
|
||||
users[1] = new User("user-b", User.WRITE);
|
||||
users[2] = new User("user-c", User.ADMIN);
|
||||
users[3] = new User("user-d", User.READ_ONLY);
|
||||
users[4] = new User(userName, User.ADMIN);
|
||||
|
||||
repository.setUserList(userName, users, false);
|
||||
|
||||
User[] reportedUsers = repository.getUserList(userName);
|
||||
assertEquals(users.length, reportedUsers.length);
|
||||
|
||||
for (int i = 0; i < users.length; i++) {
|
||||
assertEquals(users[i].getName(), reportedUsers[i].getName());
|
||||
assertEquals(users[i].getPermissionType(), reportedUsers[i].getPermissionType());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetListBadUser() throws Exception {
|
||||
|
||||
User[] users = new User[5];
|
||||
users[0] = new User("user-a", User.READ_ONLY);
|
||||
users[1] = new User("user-b", User.WRITE);
|
||||
users[2] = new User("user-c", User.ADMIN);
|
||||
users[3] = new User("user-d", User.READ_ONLY);
|
||||
users[4] = new User(userName, User.WRITE);
|
||||
try {
|
||||
repository.setUserList(userName, users, false);
|
||||
Assert.fail("Should not have been able to change current user's access!");
|
||||
}
|
||||
catch (UserAccessException e) {
|
||||
}
|
||||
|
||||
users[3] = new User("user-x", User.ADMIN);
|
||||
try {
|
||||
repository.setUserList(userName, users, false);
|
||||
Assert.fail("Should not have been able to set the user list!");
|
||||
}
|
||||
catch (UserAccessException e) {
|
||||
}
|
||||
|
||||
users[4] = new User(userName, User.ADMIN);
|
||||
repository.setUserList(userName, users, false);
|
||||
|
||||
User[] reportedUsers = repository.getUserList(userName);
|
||||
assertEquals(users.length, reportedUsers.length);
|
||||
for (int i = 0; i < users.length; i++) {
|
||||
assertEquals(users[i].getName(), reportedUsers[i].getName());
|
||||
assertEquals(users[i].getPermissionType(), reportedUsers[i].getPermissionType());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingRepository() throws Exception {
|
||||
|
||||
User[] users = new User[5];
|
||||
users[0] = new User("user-a", User.READ_ONLY);
|
||||
users[1] = new User("user-b", User.WRITE);
|
||||
users[2] = new User("user-c", User.ADMIN);
|
||||
users[3] = new User("user-d", User.READ_ONLY);
|
||||
users[4] = new User(userName, User.ADMIN);
|
||||
|
||||
repository.setUserList(userName, users, false);
|
||||
|
||||
File repRoot = new File(serverRoot, NamingUtilities.mangle(REPOSITORY_NAME));
|
||||
Repository rep = new Repository(mgr, null, repRoot, REPOSITORY_NAME);
|
||||
assertNotNull(rep);
|
||||
|
||||
User[] reportedUsers = rep.getUserList(userName);
|
||||
assertEquals(users.length, reportedUsers.length);
|
||||
for (int i = 0; i < users.length; i++) {
|
||||
assertEquals(users[i].getName(), reportedUsers[i].getName());
|
||||
assertEquals(users[i].getPermissionType(), reportedUsers[i].getPermissionType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,292 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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 ghidra.util.task;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import docking.test.AbstractDockingTest;
|
||||
import sun.awt.AppContext;
|
||||
import sun.swing.AccumulativeRunnable;
|
||||
|
||||
public class CachingSwingWorkerTest extends AbstractDockingTest {
|
||||
|
||||
private static final int ITEM_COUNT = 10;
|
||||
|
||||
@Test
|
||||
public void testSimpleThreadCase() throws InterruptedException {
|
||||
TestWorker worker = new TestWorker();
|
||||
|
||||
MyThread r1 = new MyThread(0, worker);
|
||||
MyThread r2 = new MyThread(0, worker);
|
||||
MyThread r3 = new MyThread(10, worker);
|
||||
MyThread r4 = new MyThread(20, worker);
|
||||
|
||||
worker.setDone();
|
||||
r1.join();
|
||||
r2.join();
|
||||
r3.join();
|
||||
r4.join();
|
||||
|
||||
assertEquals("number of runs", 1, worker.getNumRuns());
|
||||
|
||||
assertEquals(ITEM_COUNT, r1.size());
|
||||
assertEquals(ITEM_COUNT, r2.size());
|
||||
assertEquals(ITEM_COUNT, r3.size());
|
||||
assertEquals(ITEM_COUNT, r4.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleSwingThreadCase() {
|
||||
|
||||
disasbleTimerUsage();
|
||||
|
||||
TestWorker worker = new TestWorker();
|
||||
worker.setTaskDialogDelay(0);
|
||||
|
||||
ClientRunnable runnable = new ClientRunnable(worker);
|
||||
runSwing(runnable, false);
|
||||
|
||||
TaskDialog dialog = waitForDialogComponent(null, TaskDialog.class, 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
worker.setDone();
|
||||
worker.get(TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
|
||||
waitForPostedSwingRunnables();
|
||||
assertTrue(!dialog.isVisible());
|
||||
assertEquals("number of runs", 1, worker.getNumRuns());
|
||||
|
||||
assertEquals(ITEM_COUNT, runnable.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwingAndAnotherThreadCase() throws InterruptedException {
|
||||
|
||||
disasbleTimerUsage();
|
||||
|
||||
TestWorker worker = new TestWorker();
|
||||
worker.setTaskDialogDelay(0);
|
||||
|
||||
ClientRunnable runnable = new ClientRunnable(worker);
|
||||
runSwing(runnable, false);
|
||||
|
||||
MyThread r1 = new MyThread(100, worker);
|
||||
|
||||
TaskDialog dialog = waitForDialogComponent(null, TaskDialog.class, 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
worker.setDone();
|
||||
worker.get(TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
r1.join();
|
||||
assertEquals(ITEM_COUNT, r1.size());
|
||||
|
||||
waitForPostedSwingRunnables();
|
||||
assertTrue(!dialog.isVisible());
|
||||
assertEquals("number of runs", 1, worker.getNumRuns());
|
||||
|
||||
assertEquals(ITEM_COUNT, runnable.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwingAfterAnotherThreadCase() throws InterruptedException {
|
||||
|
||||
disasbleTimerUsage();
|
||||
|
||||
TestWorker worker = new TestWorker();
|
||||
worker.setTaskDialogDelay(0);
|
||||
|
||||
MyThread r1 = new MyThread(0, worker);
|
||||
Thread.sleep(50);
|
||||
ClientRunnable runnable = new ClientRunnable(worker);
|
||||
runSwing(runnable, false);
|
||||
|
||||
TaskDialog dialog = waitForDialogComponent(null, TaskDialog.class, 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
worker.setDone();
|
||||
worker.get(TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
r1.join();
|
||||
assertEquals(ITEM_COUNT, r1.size());
|
||||
|
||||
waitForPostedSwingRunnables();
|
||||
assertTrue(!dialog.isVisible());
|
||||
assertEquals("number of runs", 1, worker.getNumRuns());
|
||||
|
||||
assertEquals(ITEM_COUNT, runnable.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelled() {
|
||||
TestWorker worker = new TestWorker();
|
||||
worker.setTaskDialogDelay(0);
|
||||
|
||||
ClientRunnable runnable = new ClientRunnable(worker);
|
||||
runSwing(runnable, false);
|
||||
runSwing(runnable, false);
|
||||
|
||||
TaskDialog dialog = waitForDialogComponent(null, TaskDialog.class, 2000);
|
||||
assertTrue(dialog.getTitle().contains("Test Worker"));
|
||||
assertNotNull(dialog);
|
||||
|
||||
dialog.cancel();
|
||||
worker.get(TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
|
||||
waitForPostedSwingRunnables();
|
||||
assertTrue(!dialog.isVisible());
|
||||
assertEquals("number of runs", 1, worker.getNumRuns());
|
||||
|
||||
assertTrue(worker.wasCancelled);
|
||||
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
|
||||
private void disasbleTimerUsage() {
|
||||
AccumulativeRunnable<Runnable> nonTimerAccumulativeRunnable =
|
||||
new AccumulativeRunnable<Runnable>() {
|
||||
@Override
|
||||
protected void run(List<Runnable> args) {
|
||||
for (Runnable runnable : args) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Object key = getInstanceField("DO_SUBMIT_KEY", SwingWorker.class);
|
||||
|
||||
AppContext appContext = AppContext.getAppContext();
|
||||
appContext.put(key, nonTimerAccumulativeRunnable);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
class MyThread extends Thread {
|
||||
ClientRunnable runnable;
|
||||
|
||||
MyThread(int delay, TestWorker worker) {
|
||||
runnable = new ClientRunnable(worker);
|
||||
try {
|
||||
Thread.sleep(delay);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// whatever
|
||||
}
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
int size() {
|
||||
if (runnable == null) {
|
||||
return 0;
|
||||
}
|
||||
return runnable.size();
|
||||
}
|
||||
}
|
||||
|
||||
class TestWorker extends CachingSwingWorker<List<String>> {
|
||||
private volatile boolean done = false;
|
||||
private int numRuns = 0;
|
||||
private volatile boolean wasCancelled = false;
|
||||
|
||||
public TestWorker() {
|
||||
super("Test Worker", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> runInBackground(TaskMonitor monitor) {
|
||||
monitor.initialize(ITEM_COUNT);
|
||||
numRuns++;
|
||||
List<String> list = new ArrayList<String>();
|
||||
int count = 0;
|
||||
while (!done || count < ITEM_COUNT) {
|
||||
if (monitor.isCancelled()) {
|
||||
wasCancelled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (count < ITEM_COUNT) {
|
||||
String message = "line " + count;
|
||||
list.add(message);
|
||||
monitor.setProgress(count);
|
||||
monitor.setMessage(message);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (count > 600) {
|
||||
list.add("timeout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void setDone() {
|
||||
done = true;
|
||||
}
|
||||
|
||||
boolean wasCancelled() {
|
||||
return wasCancelled;
|
||||
}
|
||||
|
||||
int getNumRuns() {
|
||||
return numRuns;
|
||||
}
|
||||
}
|
||||
|
||||
class ClientRunnable implements Runnable {
|
||||
List<String> result;
|
||||
private TestWorker worker;
|
||||
|
||||
ClientRunnable(TestWorker worker) {
|
||||
this.worker = worker;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return result == null ? 0 : result.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
result = worker.get(TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue