added model.close() to model usages. Cleanup of generated temp folders.

This commit is contained in:
hneemann 2018-03-09 12:13:04 +01:00
parent b40023b01a
commit 5c9003e59d
9 changed files with 147 additions and 148 deletions

View File

@ -6,6 +6,8 @@
package de.neemann.digital.core.extern;
import de.neemann.digital.lang.Lang;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -17,6 +19,7 @@ import java.util.Arrays;
* Helper to start and wait for a process.
*/
public final class ProcessStarter {
private static final Logger LOGGER = LoggerFactory.getLogger(ProcessStarter.class);
private ProcessStarter() {
}
@ -38,7 +41,7 @@ public final class ProcessStarter {
try {
p = pb.start();
} catch (IOException e) {
throw new IOException(Lang.get("err_couldNotStartProcess_N", Arrays.toString(args)));
throw new CouldNotStartProcessException(Lang.get("err_couldNotStartProcess_N", Arrays.toString(args)));
}
ReaderThread rt = new ReaderThread(p.getInputStream());
rt.start();
@ -99,11 +102,10 @@ public final class ProcessStarter {
for (File f : list) {
if (f.isDirectory())
removeFolder(f);
else
f.delete();
else if (!f.delete()) LOGGER.warn("file " + f + " could not be deleted!");
}
}
dir.delete();
if (!dir.delete()) LOGGER.warn("dir " + dir + " could not be deleted!");
}
/**
@ -131,4 +133,12 @@ public final class ProcessStarter {
return null;
}
/**
* Thrown if process could not be started
*/
public static final class CouldNotStartProcessException extends IOException {
private CouldNotStartProcessException(String message) {
super(message);
}
}
}

View File

@ -8,6 +8,8 @@ package de.neemann.digital.core.extern.handler;
import de.neemann.digital.core.ObservableValue;
import de.neemann.digital.core.ObservableValues;
import de.neemann.digital.lang.Lang;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.LinkedList;
@ -22,6 +24,7 @@ import java.util.LinkedList;
* The last bit needs to be followed by an end of line character.
*/
public class StdIOInterface implements ProcessInterface {
private static final Logger LOGGER = LoggerFactory.getLogger(StdIOInterface.class);
private static final String PREFIX = "Digital:";
private static final int MAX_CONSOLE_LINES = 30;
private static final long TIMEOUT = 5000;
@ -69,6 +72,7 @@ public class StdIOInterface implements ProcessInterface {
consoleOut = new LinkedList<>();
terminated = false;
thread = new Thread(() -> {
LOGGER.debug("reader-thread started");
try {
String line;
while ((line = reader.readLine()) != null) {
@ -91,6 +95,7 @@ public class StdIOInterface implements ProcessInterface {
terminated = true;
lock.notify();
}
LOGGER.debug("reader-thread terminated");
});
thread.setDaemon(true);
thread.start();

View File

@ -544,7 +544,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
// check model for errors
try {
new ModelCreator(circuitComponent.getCircuit(), library).createModel(false);
new ModelCreator(circuitComponent.getCircuit(), library).createModel(false).close();
} catch (PinException | NodeException | ElementNotFoundException e) {
showErrorWithoutARunningModel(Lang.get("msg_modelHasErrors"), e);
return;
@ -924,14 +924,18 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
public void actionPerformed(ActionEvent e) {
try {
Model model = new ModelCreator(circuitComponent.getCircuit(), library).createModel(false);
model.setWindowPosManager(windowPosManager);
SpeedTest speedTest = new SpeedTest(model);
String frequency = format.format(speedTest.calculate() / 1000);
circuitComponent.getCircuit().clearState();
SwingUtilities.invokeLater(() -> {
windowPosManager.closeAll();
JOptionPane.showMessageDialog(Main.this, Lang.get("msg_frequency_N", frequency));
});
try {
model.setWindowPosManager(windowPosManager);
SpeedTest speedTest = new SpeedTest(model);
String frequency = format.format(speedTest.calculate() / 1000);
circuitComponent.getCircuit().clearState();
SwingUtilities.invokeLater(() -> {
windowPosManager.closeAll();
JOptionPane.showMessageDialog(Main.this, Lang.get("msg_frequency_N", frequency));
});
} finally {
model.close();
}
} catch (Exception e1) {
showErrorWithoutARunningModel(Lang.get("msg_speedTestError"), e1);
}
@ -1036,17 +1040,20 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
public void actionPerformed(ActionEvent e) {
try {
Model model = new ModelCreator(circuitComponent.getCircuit(), library).createModel(false);
if (model.isInvalidSignal())
new ErrorMessage(Lang.get("msg_invalidSignalsAnalysed")).show(Main.this);
else
new TableDialog(Main.this,
new ModelAnalyser(model).analyse(),
library,
shapeFactory,
getBaseFileName())
.setVisible(true);
ensureModelIsStopped();
try {
if (model.isInvalidSignal())
new ErrorMessage(Lang.get("msg_invalidSignalsAnalysed")).show(Main.this);
else
new TableDialog(Main.this,
new ModelAnalyser(model).analyse(),
library,
shapeFactory,
getBaseFileName())
.setVisible(true);
ensureModelIsStopped();
} finally {
model.close();
}
} catch (PinException | NodeException | AnalyseException | ElementNotFoundException | BacktrackException | RuntimeException e1) {
showErrorWithoutARunningModel(Lang.get("msg_analyseErr"), e1);
}
@ -1081,16 +1088,20 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
private void orderMeasurements() {
try {
Model m = new ModelCreator(circuitComponent.getCircuit(), library).createModel(false);
ensureModelIsStopped();
ArrayList<String> names = new ArrayList<>();
for (Signal s : m.getSignals())
names.add(s.getName());
new OrderMerger<String, String>(circuitComponent.getCircuit().getMeasurementOrdering()).order(names);
ElementOrderer.ListOrder<String> o = new ElementOrderer.ListOrder<>(names);
if (new ElementOrderer<>(Main.this, Lang.get("menu_orderMeasurements"), o)
.addOkButton()
.showDialog()) {
circuitComponent.modify(new ModifyMeasurementOrdering(names));
try {
ensureModelIsStopped();
ArrayList<String> names = new ArrayList<>();
for (Signal s : m.getSignals())
names.add(s.getName());
new OrderMerger<String, String>(circuitComponent.getCircuit().getMeasurementOrdering()).order(names);
ElementOrderer.ListOrder<String> o = new ElementOrderer.ListOrder<>(names);
if (new ElementOrderer<>(Main.this, Lang.get("menu_orderMeasurements"), o)
.addOkButton()
.showDialog()) {
circuitComponent.modify(new ModifyMeasurementOrdering(names));
}
} finally {
m.close();
}
} catch (NodeException | PinException | ElementNotFoundException | RuntimeException e) {
showErrorWithoutARunningModel(Lang.get("msg_errorCreatingModel"), e);

View File

@ -787,13 +787,16 @@ public final class EditorFactory {
try {
CircuitComponent circuitComponent = main.getCircuitComponent();
Model model = new ModelCreator(circuitComponent.getCircuit(), circuitComponent.getLibrary()).createModel(false);
romEditorDialog = new ROMEditorDialog(
getAttributeDialog(),
model,
romManager);
if (romEditorDialog.showDialog())
romManager = romEditorDialog.getROMManager();
try {
romEditorDialog = new ROMEditorDialog(
getAttributeDialog(),
model,
romManager);
if (romEditorDialog.showDialog())
romManager = romEditorDialog.getROMManager();
} finally {
model.close();
}
} catch (ElementNotFoundException | PinException | NodeException e) {
new ErrorMessage(Lang.get("msg_errorCreatingModel")).addCause(e).show(getAttributeDialog());
}

View File

@ -115,30 +115,34 @@ public class ValueTableDialog extends JDialog {
int errorTabIndex = -1;
for (TestSet ts : tsl) {
Model model = new ModelCreator(circuit, library).createModel(false);
try {
TestExecutor testExecutor = new TestExecutor(ts.data).create(model);
TestExecutor testExecutor = new TestExecutor(ts.data).create(model);
if (testExecutor.getException() != null)
SwingUtilities.invokeLater(new ErrorMessage(Lang.get("msg_errorWhileExecutingTests_N0", ts.name)).addCause(testExecutor.getException()).setComponent(this));
if (testExecutor.getException() != null)
SwingUtilities.invokeLater(new ErrorMessage(Lang.get("msg_errorWhileExecutingTests_N0", ts.name)).addCause(testExecutor.getException()).setComponent(this));
String tabName;
Icon tabIcon;
if (testExecutor.allPassed()) {
tabName = Lang.get("msg_test_N_Passed", ts.name);
tabIcon = ICON_PASSED;
} else {
tabName = Lang.get("msg_test_N_Failed", ts.name);
tabIcon = ICON_FAILED;
errorTabIndex = i;
String tabName;
Icon tabIcon;
if (testExecutor.allPassed()) {
tabName = Lang.get("msg_test_N_Passed", ts.name);
tabIcon = ICON_PASSED;
} else {
tabName = Lang.get("msg_test_N_Failed", ts.name);
tabIcon = ICON_FAILED;
errorTabIndex = i;
}
if (testExecutor.toManyResults())
tabName += " " + Lang.get("msg_test_missingLines");
tp.addTab(tabName, tabIcon, new JScrollPane(createTable(testExecutor.getResult())));
if (testExecutor.toManyResults())
tp.setToolTipTextAt(i, new LineBreaker().toHTML().breakLines(Lang.get("msg_test_missingLines_tt")));
resultTableData.add(testExecutor.getResult());
i++;
} finally {
model.close();
}
if (testExecutor.toManyResults())
tabName += " " + Lang.get("msg_test_missingLines");
tp.addTab(tabName, tabIcon, new JScrollPane(createTable(testExecutor.getResult())));
if (testExecutor.toManyResults())
tp.setToolTipTextAt(i, new LineBreaker().toHTML().breakLines(Lang.get("msg_test_missingLines_tt")));
resultTableData.add(testExecutor.getResult());
i++;
}
if (errorTabIndex >= 0)
tp.setSelectedIndex(errorTabIndex);

View File

@ -72,6 +72,7 @@ public class BuilderExpressionCreatorTest extends TestCase {
private void check(Model m) throws AnalyseException, NodeException, BacktrackException, PinException {
TruthTable tt = new ModelAnalyser(m).analyse();
m.close();
assertEquals(1,tt.getResultCount());
BoolTable r = tt.getResult(0);
assertEquals(4, r.size());
@ -79,6 +80,7 @@ public class BuilderExpressionCreatorTest extends TestCase {
assertEquals(ThreeStateValue.one ,r.get(1));
assertEquals(ThreeStateValue.one ,r.get(2));
assertEquals(ThreeStateValue.zero ,r.get(3));
}
private Model create(ExpressionListenerStore els, ExpressionModifier modifier) throws ExpressionException, FormatterException, ElementNotFoundException, PinException, NodeException {

View File

@ -7,6 +7,7 @@ package de.neemann.digital.hdl.vhdl;
import de.neemann.digital.core.ExceptionWithOrigin;
import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.extern.ProcessStarter;
import de.neemann.digital.draw.elements.PinException;
import de.neemann.digital.draw.library.ElementNotFoundException;
import de.neemann.digital.hdl.model.HDLException;
@ -96,19 +97,18 @@ public class TestInSimulator extends TestCase {
private void check(File file) throws PinException, NodeException, ElementNotFoundException, IOException, FileScanner.SkipAllException, HDLException {
ToBreakRunner br = new ToBreakRunner(file);
File dir = Files.createTempDirectory("digital_vhdl_" + getTime() + "_").toFile();
File vhdlFile = new File(dir, file.getName().replace('.', '_') + ".vhdl");
CodePrinter out = new CodePrinter(vhdlFile);
try (VHDLGenerator vhdl = new VHDLGenerator(br.getLibrary(), out)) {
vhdl.omitClockDividers().export(br.getCircuit());
VHDLTestBenchCreator tb = vhdl.getTestBenches();
out.close();
runGHDL(vhdlFile, tb.getTestFileWritten());
try {
File vhdlFile = new File(dir, file.getName().replace('.', '_') + ".vhdl");
CodePrinter out = new CodePrinter(vhdlFile);
try (VHDLGenerator vhdl = new VHDLGenerator(br.getLibrary(), out)) {
vhdl.omitClockDividers().export(br.getCircuit());
VHDLTestBenchCreator tb = vhdl.getTestBenches();
out.close();
runGHDL(vhdlFile, tb.getTestFileWritten());
}
} finally {
ProcessStarter.removeFolder(dir);
}
File[] filesInDir = dir.listFiles();
if (filesInDir != null)
for (File f : filesInDir)
if (!f.delete()) LOGGER.warn("file " + f + " could not be deleted!");
if (!dir.delete()) LOGGER.warn("dir " + dir + " could not be deleted!");
}
private void runGHDL(File vhdlFile, ArrayList<File> testFileWritten) throws IOException, FileScanner.SkipAllException, HDLException {
@ -135,29 +135,11 @@ public class TestInSimulator extends TestCase {
}
private String startProcess(File dir, String... args) throws IOException, FileScanner.SkipAllException {
//System.out.println("start " + Arrays.toString(args));
ProcessBuilder pb = new ProcessBuilder(args).redirectErrorStream(true).directory(dir);
Process p;
try {
p = pb.start();
} catch (IOException e) {
return ProcessStarter.start(dir, args);
} catch (ProcessStarter.CouldNotStartProcessException e) {
throw new FileScanner.SkipAllException("ghdl (https://github.com/tgingold/ghdl) is not installed! Add ghdl binary to the system path or set system property 'ghdl' to ghdl binary");
}
ReaderThread rt = new ReaderThread(p.getInputStream());
rt.start();
try {
int exitValue = p.waitFor();
rt.join();
String output = rt.toString();
if (exitValue != 0)
throw new IOException("exit value not null: " + exitValue + "\n" + output);
return output;
} catch (InterruptedException e) {
throw new IOException(e);
}
}
private String getTime() {
@ -165,35 +147,4 @@ public class TestInSimulator extends TestCase {
return f.format(new Date());
}
private static final class ReaderThread extends Thread {
private final ByteArrayOutputStream baos;
private final InputStream in;
private ReaderThread(InputStream in) {
this.in = in;
baos = new ByteArrayOutputStream();
}
@Override
public void run() {
try {
try {
byte[] buffer = new byte[4096];
int len;
while ((len = in.read(buffer)) > 0)
baos.write(buffer, 0, len);
} finally {
in.close();
}
} catch (IOException e) {
// do nothing, simply end the thread
}
}
@Override
public String toString() {
return baos.toString();
}
}
}

View File

@ -65,35 +65,43 @@ public class TestExamples extends TestCase {
} else
throw e;
}
boolean isLib = dig.getPath().replace('\\', '/').contains("/lib/");
assertTrue("wrong locked mode", isLib == br.getCircuit().getAttributes().get(Keys.LOCKED_MODE));
try {
for (VisualElement el : br.getCircuit().getElements())
if (el.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION)) {
String label = el.getElementAttributes().getCleanLabel();
TestCaseDescription td = el.getElementAttributes().get(TestCaseElement.TESTDATA);
boolean isLib = dig.getPath().replace('\\', '/').contains("/lib/");
Model model = new ModelCreator(br.getCircuit(), br.getLibrary()).createModel(false);
TestExecutor tr = new TestExecutor(td).create(model);
assertTrue("wrong locked mode", isLib == br.getCircuit().getAttributes().get(Keys.LOCKED_MODE));
if (label.contains("Failing"))
assertFalse(dig.getName() + ":" + label, tr.allPassed());
else
assertTrue(dig.getName() + ":" + label, tr.allPassed());
try {
for (VisualElement el : br.getCircuit().getElements())
if (el.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION)) {
testCasesInFiles++;
}
} catch (Exception e) {
if (shouldFail) {
return;
} else
throw e;
String label = el.getElementAttributes().getCleanLabel();
TestCaseDescription td = el.getElementAttributes().get(TestCaseElement.TESTDATA);
Model model = new ModelCreator(br.getCircuit(), br.getLibrary()).createModel(false);
try {
TestExecutor tr = new TestExecutor(td).create(model);
if (label.contains("Failing"))
assertFalse(dig.getName() + ":" + label, tr.allPassed());
else
assertTrue(dig.getName() + ":" + label, tr.allPassed());
testCasesInFiles++;
} finally {
model.close();
}
}
} catch (Exception e) {
if (shouldFail) {
return;
} else
throw e;
}
assertFalse("File should fail but doesn't!", shouldFail);
} finally {
br.close();
}
assertFalse("File should fail but doesn't!", shouldFail);
}
}

View File

@ -139,4 +139,9 @@ public class ToBreakRunner {
public ElementLibrary getLibrary() {
return library;
}
public void close() {
if (model != null)
model.close();
}
}