mirror of
https://github.com/eclipse-cdt/cdt
synced 2024-10-28 12:09:40 +01:00
Bug 562164 - Add JUnit tests for IMemoryImporter and IMemoryExporter
* Added FileExport to implement base flow * Added ExportRequest to aggregate operation configuration * Extracted PlainTextExport extends FileExport * Added ReadMemory to simplify interaction interface * Extracted AddressableSize to reduce code duplication Change-Id: I848c922cd1300799c0e9d1bff8213e8b06edc41c Signed-off-by: Alexander Fedorov <alexander.fedorov@arsysop.ru>
This commit is contained in:
parent
0ab57c346a
commit
53a665be69
8 changed files with 358 additions and 111 deletions
|
@ -0,0 +1,70 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 ArSysOp and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Alexander Fedorov (ArSysOp) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.core.memory.transport;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
*
|
||||
* Aggregates memory export configuration
|
||||
*
|
||||
* @since 0.1
|
||||
*
|
||||
*/
|
||||
public final class ExportRequest {
|
||||
|
||||
private final BigInteger start;
|
||||
private final BigInteger end;
|
||||
private final BigInteger addressable;
|
||||
private final ReadMemory read;
|
||||
|
||||
public ExportRequest(BigInteger start, BigInteger end, BigInteger addressable, ReadMemory read) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.addressable = addressable;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return starting offset
|
||||
*/
|
||||
public BigInteger start() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return ending offset
|
||||
*/
|
||||
public BigInteger end() {
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return addressable size
|
||||
*/
|
||||
public BigInteger addressable() {
|
||||
return addressable;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return reader
|
||||
*/
|
||||
public ReadMemory read() {
|
||||
return read;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 ArSysOp and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Alexander Fedorov (ArSysOp) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.core.memory.transport;
|
||||
|
||||
import java.io.File;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.eclipse.core.runtime.ICoreRunnable;
|
||||
|
||||
/**
|
||||
* Exports memory information to a given file
|
||||
*
|
||||
* @since 0.1
|
||||
*/
|
||||
public abstract class FileExport<O extends AutoCloseable> implements ICoreRunnable {
|
||||
|
||||
protected final BigInteger start;
|
||||
protected final BigInteger end;
|
||||
protected final BigInteger addressable;
|
||||
protected final ReadMemory read;
|
||||
|
||||
protected final File file;
|
||||
|
||||
protected FileExport(File input, ExportRequest request) {
|
||||
this.file = input;
|
||||
this.start = request.start();
|
||||
this.end = request.end();
|
||||
this.addressable = request.addressable();
|
||||
this.read = request.read();
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,7 @@ import java.math.BigInteger;
|
|||
* @since 0.1
|
||||
*
|
||||
*/
|
||||
public class ImportRequest {
|
||||
public final class ImportRequest {
|
||||
|
||||
private final BigInteger base;
|
||||
private final BigInteger start;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 ArSysOp and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Alexander Fedorov (ArSysOp) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.core.memory.transport;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
|
||||
/**
|
||||
* Reads an array of bytes using the given offset
|
||||
*
|
||||
* @since 0.1
|
||||
*/
|
||||
public interface ReadMemory {
|
||||
|
||||
/**
|
||||
* Reads an array of bytes from a memory starting from the given offset.
|
||||
*
|
||||
* @param offset
|
||||
* @return the obtained data
|
||||
* @throws DebugException
|
||||
*/
|
||||
byte[] from(BigInteger offset) throws DebugException;
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 ArSysOp and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Alexander Fedorov (ArSysOp) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.internal.core.memory.transport;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.eclipse.cdt.debug.core.memory.transport.ReadMemory;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.model.IMemoryBlockExtension;
|
||||
import org.eclipse.debug.core.model.MemoryByte;
|
||||
|
||||
/**
|
||||
* Reads memory from the given {@link IMemoryBlockExtension}
|
||||
*
|
||||
*/
|
||||
public final class ReadMemoryBlock implements ReadMemory {
|
||||
|
||||
private final IMemoryBlockExtension memory;
|
||||
private final long unit;
|
||||
|
||||
public ReadMemoryBlock(IMemoryBlockExtension memory) {
|
||||
this.memory = memory;
|
||||
this.unit = BigInteger.valueOf(1).longValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] from(BigInteger offset) throws DebugException {
|
||||
MemoryByte[] received = memory.getBytesFromOffset(offset, unit);
|
||||
byte[] bytes = new byte[received.length];
|
||||
for (int i = 0; i < received.length; i++) {
|
||||
bytes[i] = received[i].getValue();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020 ArSysOp and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Alexander Fedorov (ArSysOp) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.internal.ui.memory.transport;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.model.IMemoryBlockExtension;
|
||||
|
||||
public class AddressableSize implements Supplier<BigInteger> {
|
||||
|
||||
private final IMemoryBlockExtension memory;
|
||||
|
||||
public AddressableSize(IMemoryBlockExtension memory) {
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger get() {
|
||||
try {
|
||||
return BigInteger.valueOf(memory.getAddressableSize());
|
||||
} catch (DebugException e1) {
|
||||
// sane value for most cases
|
||||
return BigInteger.ONE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2020 Wind River Systems, Inc. and others.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
|
||||
* Alexander Fedorov (ArSysOp) - headless part extraction
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.ui.memory.transport;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.eclipse.cdt.debug.core.memory.transport.ExportRequest;
|
||||
import org.eclipse.cdt.debug.core.memory.transport.FileExport;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
|
||||
final class PlainTextExport extends FileExport<FileWriter> {
|
||||
|
||||
protected PlainTextExport(File output, ExportRequest request) {
|
||||
super(output, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(IProgressMonitor monitor) throws CoreException {
|
||||
try {
|
||||
// These variables control how the output will be formatted
|
||||
// The output data is split by chunks of 1 addressable unit size.
|
||||
final BigInteger dataCellSize = BigInteger.valueOf(1);
|
||||
// show 32 bytes of data per line, total. Adjust number of columns to compensate
|
||||
// for longer addressable unit size
|
||||
final BigInteger numberOfColumns = BigInteger.valueOf(32).divide(addressable);
|
||||
// deduce the number of data chunks to be output, per line
|
||||
final BigInteger dataCellsPerLine = dataCellSize.multiply(numberOfColumns);
|
||||
BigInteger transferAddress = start;
|
||||
FileWriter writer = new FileWriter(file);
|
||||
BigInteger jobs = end.subtract(transferAddress).divide(dataCellsPerLine);
|
||||
BigInteger factor = BigInteger.ONE;
|
||||
if (jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) {
|
||||
factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF));
|
||||
jobs = jobs.divide(factor);
|
||||
}
|
||||
monitor.beginTask(Messages.getString("Exporter.ProgressTitle"), jobs.intValue()); //$NON-NLS-1$
|
||||
BigInteger jobCount = BigInteger.ZERO;
|
||||
while (transferAddress.compareTo(end) < 0 && !monitor.isCanceled()) {
|
||||
BigInteger length = dataCellsPerLine;
|
||||
if (end.subtract(transferAddress).compareTo(length) < 0)
|
||||
length = end.subtract(transferAddress);
|
||||
monitor.subTask(String.format(Messages.getString("Exporter.Progress"), length.toString(10), //$NON-NLS-1$
|
||||
transferAddress.toString(16)));
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (int i = 0; i < length.divide(dataCellSize).intValue(); i++) {
|
||||
if (i != 0) {
|
||||
buf.append(" "); //$NON-NLS-1$
|
||||
}
|
||||
BigInteger from = transferAddress.add(dataCellSize.multiply(BigInteger.valueOf(i)));
|
||||
byte[] bytes = read.from(from);
|
||||
for (int byteIndex = 0; byteIndex < bytes.length; byteIndex++) {
|
||||
String bString = BigInteger.valueOf(0xFF & bytes[byteIndex]).toString(16);
|
||||
if (bString.length() == 1) {
|
||||
buf.append("0"); //$NON-NLS-1$
|
||||
}
|
||||
buf.append(bString);
|
||||
}
|
||||
}
|
||||
writer.write(buf.toString().toUpperCase());
|
||||
writer.write("\n"); //$NON-NLS-1$
|
||||
transferAddress = transferAddress.add(length);
|
||||
jobCount = jobCount.add(BigInteger.ONE);
|
||||
if (jobCount.compareTo(factor) == 0) {
|
||||
jobCount = BigInteger.ZERO;
|
||||
monitor.worked(1);
|
||||
}
|
||||
}
|
||||
writer.close();
|
||||
monitor.done();
|
||||
} catch (IOException ex) {
|
||||
MemoryTransportPlugin.getDefault().getLog()
|
||||
.log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrFile"), ex)); //$NON-NLS-1$
|
||||
throw new CoreException(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrFile"), ex)); //$NON-NLS-1$
|
||||
|
||||
} catch (DebugException ex) {
|
||||
MemoryTransportPlugin.getDefault().getLog()
|
||||
.log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrReadTarget"), ex)); //$NON-NLS-1$
|
||||
throw new CoreException(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrReadTarget"), ex)); //$NON-NLS-1$
|
||||
} catch (Exception ex) {
|
||||
MemoryTransportPlugin.getDefault().getLog()
|
||||
.log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.INTERNAL_ERROR, Messages.getString("Exporter.Falure"), ex)); //$NON-NLS-1$
|
||||
throw new CoreException(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.INTERNAL_ERROR, Messages.getString("Exporter.Falure"), ex)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -15,19 +15,16 @@
|
|||
package org.eclipse.cdt.debug.ui.memory.transport;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.eclipse.cdt.debug.core.memory.transport.ExportRequest;
|
||||
import org.eclipse.cdt.debug.core.memory.transport.ReadMemory;
|
||||
import org.eclipse.cdt.debug.internal.core.memory.transport.ReadMemoryBlock;
|
||||
import org.eclipse.cdt.debug.internal.core.memory.transport.TransportJob;
|
||||
import org.eclipse.cdt.debug.internal.ui.memory.transport.AddressableSize;
|
||||
import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryExporter;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.model.IMemoryBlock;
|
||||
import org.eclipse.debug.core.model.IMemoryBlockExtension;
|
||||
import org.eclipse.debug.core.model.MemoryByte;
|
||||
import org.eclipse.jface.dialogs.IDialogSettings;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.KeyEvent;
|
||||
|
@ -453,110 +450,13 @@ public class PlainTextExporter implements IMemoryExporter {
|
|||
|
||||
@Override
|
||||
public void exportMemory() {
|
||||
Job job = new Job("Memory Export to Plain Text File") { //$NON-NLS-1$
|
||||
@Override
|
||||
public IStatus run(IProgressMonitor monitor) {
|
||||
try {
|
||||
final BigInteger addressableSize = getAdressableSize();
|
||||
|
||||
// These variables control how the output will be formatted
|
||||
|
||||
// The output data is split by chunks of 1 addressable unit size.
|
||||
final BigInteger dataCellSize = BigInteger.valueOf(1);
|
||||
// show 32 bytes of data per line, total. Adjust number of columns to compensate
|
||||
// for longer addressable unit size
|
||||
final BigInteger numberOfColumns = BigInteger.valueOf(32).divide(addressableSize);
|
||||
// deduce the number of data chunks to be output, per line
|
||||
final BigInteger dataCellsPerLine = dataCellSize.multiply(numberOfColumns);
|
||||
|
||||
BigInteger transferAddress = fStartAddress;
|
||||
|
||||
FileWriter writer = new FileWriter(fOutputFile);
|
||||
|
||||
BigInteger jobs = fEndAddress.subtract(transferAddress).divide(dataCellsPerLine);
|
||||
BigInteger factor = BigInteger.ONE;
|
||||
if (jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) {
|
||||
factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF));
|
||||
jobs = jobs.divide(factor);
|
||||
}
|
||||
|
||||
monitor.beginTask(Messages.getString("Exporter.ProgressTitle"), jobs.intValue()); //$NON-NLS-1$
|
||||
|
||||
BigInteger jobCount = BigInteger.ZERO;
|
||||
while (transferAddress.compareTo(fEndAddress) < 0 && !monitor.isCanceled()) {
|
||||
BigInteger length = dataCellsPerLine;
|
||||
if (fEndAddress.subtract(transferAddress).compareTo(length) < 0)
|
||||
length = fEndAddress.subtract(transferAddress);
|
||||
|
||||
monitor.subTask(String.format(Messages.getString("Exporter.Progress"), length.toString(10), //$NON-NLS-1$
|
||||
transferAddress.toString(16)));
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < length.divide(dataCellSize).intValue(); i++) {
|
||||
if (i != 0)
|
||||
buf.append(" "); //$NON-NLS-1$
|
||||
MemoryByte bytes[] = ((IMemoryBlockExtension) fMemoryBlock).getBytesFromAddress(
|
||||
transferAddress.add(dataCellSize.multiply(BigInteger.valueOf(i))),
|
||||
dataCellSize.longValue());
|
||||
for (int byteIndex = 0; byteIndex < bytes.length; byteIndex++) {
|
||||
String bString = BigInteger.valueOf(0xFF & bytes[byteIndex].getValue()).toString(16);
|
||||
if (bString.length() == 1)
|
||||
buf.append("0"); //$NON-NLS-1$
|
||||
buf.append(bString);
|
||||
}
|
||||
}
|
||||
|
||||
writer.write(buf.toString().toUpperCase());
|
||||
writer.write("\n"); //$NON-NLS-1$
|
||||
|
||||
transferAddress = transferAddress.add(length);
|
||||
|
||||
jobCount = jobCount.add(BigInteger.ONE);
|
||||
if (jobCount.compareTo(factor) == 0) {
|
||||
jobCount = BigInteger.ZERO;
|
||||
monitor.worked(1);
|
||||
}
|
||||
}
|
||||
|
||||
writer.close();
|
||||
monitor.done();
|
||||
} catch (IOException ex) {
|
||||
MemoryTransportPlugin.getDefault().getLog()
|
||||
.log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrFile"), ex)); //$NON-NLS-1$
|
||||
return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrFile"), ex); //$NON-NLS-1$
|
||||
|
||||
} catch (DebugException ex) {
|
||||
MemoryTransportPlugin.getDefault().getLog()
|
||||
.log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrReadTarget"), ex)); //$NON-NLS-1$
|
||||
return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.REQUEST_FAILED, Messages.getString("Exporter.ErrReadTarget"), ex); //$NON-NLS-1$
|
||||
} catch (Exception ex) {
|
||||
MemoryTransportPlugin.getDefault().getLog()
|
||||
.log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.INTERNAL_ERROR, Messages.getString("Exporter.Falure"), ex)); //$NON-NLS-1$
|
||||
return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(),
|
||||
DebugException.INTERNAL_ERROR, Messages.getString("Exporter.Falure"), ex); //$NON-NLS-1$
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
};
|
||||
ReadMemory read = new ReadMemoryBlock((IMemoryBlockExtension) fMemoryBlock);
|
||||
BigInteger addressable = new AddressableSize((IMemoryBlockExtension) fMemoryBlock).get();
|
||||
ExportRequest request = new ExportRequest(fStartAddress, fEndAddress, addressable, read);
|
||||
PlainTextExport memoryExport = new PlainTextExport(fOutputFile, request);
|
||||
TransportJob job = new TransportJob("Memory Export to Plain Text File", memoryExport);
|
||||
job.setUser(true);
|
||||
job.schedule();
|
||||
}
|
||||
|
||||
private BigInteger getAdressableSize() {
|
||||
BigInteger addressableSize;
|
||||
try {
|
||||
addressableSize = BigInteger.valueOf(((IMemoryBlockExtension) fMemoryBlock).getAddressableSize());
|
||||
} catch (DebugException e1) {
|
||||
// sane value for most cases
|
||||
addressableSize = BigInteger.ONE;
|
||||
}
|
||||
return addressableSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue