From bb776c610bd6ecbdb303f6d689275204e1668354 Mon Sep 17 00:00:00 2001
From: arkpar <arkady.paronyan@gmail.com>
Date: Tue, 14 Apr 2015 14:57:28 +0200
Subject: [PATCH 1/5] fixed debugger panes default size

---
 mix/qml/DebugInfoList.qml    |  8 ++++++--
 mix/qml/NewProjectDialog.qml |  1 +
 mix/qml/StateDialog.qml      | 13 ++++++++-----
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/mix/qml/DebugInfoList.qml b/mix/qml/DebugInfoList.qml
index b479d6d28..9adac7b5c 100644
--- a/mix/qml/DebugInfoList.qml
+++ b/mix/qml/DebugInfoList.qml
@@ -33,7 +33,11 @@ ColumnLayout {
 		if (storageContainer.parent.parent.height === 25)
 			storageContainer.collapse();
 		else
+		{
+			if (storageContainer.parent.parent.height === 0)
+				storageContainer.parent.parent.height = 200;
 			storageContainer.expand();
+		}
 	}
 
 	RowLayout {
@@ -63,6 +67,8 @@ ColumnLayout {
 					if (collapsed)
 					{
 						storageContainer.expand();
+						if (storedHeight <= 25)
+							storedHeight = 200;
 						storageContainer.parent.parent.height = storedHeight;
 					}
 					else
@@ -105,8 +111,6 @@ ColumnLayout {
 			height: parent.height - 6
 			onHeightChanged:  {
 				if (height <= 0 && collapsible) {
-					if (storedHeight <= 0)
-						storedHeight = 200;
 					storageContainer.collapse();
 				}
 				else if (height > 0 && collapsed) {
diff --git a/mix/qml/NewProjectDialog.qml b/mix/qml/NewProjectDialog.qml
index 611f18049..77b6c513a 100644
--- a/mix/qml/NewProjectDialog.qml
+++ b/mix/qml/NewProjectDialog.qml
@@ -28,6 +28,7 @@ Item
 	Dialog {
 		id: newProjectWin
 		modality: Qt.ApplicationModal
+		title: qsTr("New Project");
 
 		width: 640
 		height: 120
diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml
index d609808ea..0293c5c35 100644
--- a/mix/qml/StateDialog.qml
+++ b/mix/qml/StateDialog.qml
@@ -47,12 +47,15 @@ Dialog {
 		stateAccounts = [];
 		var miner = 0;
 
-		for (var k = 0; k < item.accounts.length; k++)
+		if (item.miner)
 		{
-			accountsModel.append(item.accounts[k]);
-			stateAccounts.push(item.accounts[k]);
-			if (item.accounts[k].name === item.miner.name)
-				miner = k;
+			for (var k = 0; k < item.accounts.length; k++)
+			{
+				accountsModel.append(item.accounts[k]);
+				stateAccounts.push(item.accounts[k]);
+				if (item.accounts[k].name === item.miner.name)
+					miner = k;
+			}
 		}
 
 		visible = true;

From 48648ac178b329a70cb379be7300771619252eb2 Mon Sep 17 00:00:00 2001
From: arkpar <arkady.paronyan@gmail.com>
Date: Wed, 15 Apr 2015 11:54:24 +0200
Subject: [PATCH 2/5] more tests

---
 mix/ClientModel.cpp             |  4 +--
 mix/qml/Debugger.qml            |  4 +++
 mix/test/qml/TestMain.qml       |  2 ++
 mix/test/qml/js/TestDebugger.js | 64 +++++++++++++++++++++++++++++++++
 mix/test/qml/js/TestProject.js  |  1 +
 5 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp
index 807c27adf..3478a88fa 100644
--- a/mix/ClientModel.cpp
+++ b/mix/ClientModel.cpp
@@ -401,9 +401,9 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
 				AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex];
 				auto functionIter = contract->functions().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end));
 				if (functionIter != contract->functions().end() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty()))
-					solCallStack.push_back(QVariant::fromValue(functionIter.value()));
+					solCallStack.push_front(QVariant::fromValue(functionIter.value()));
 				else if (prevInstruction.getJumpType() == AssemblyItem::JumpType::OutOfFunction && !solCallStack.empty())
-					solCallStack.pop_back();
+					solCallStack.pop_front();
 			}
 
 			//format solidity context values
diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml
index 3b8a87e8a..87a27cf79 100644
--- a/mix/qml/Debugger.qml
+++ b/mix/qml/Debugger.qml
@@ -17,6 +17,10 @@ Rectangle {
 	property alias solLocals: solLocals
 	property alias solStorage: solStorage
 	property alias solCallStack: solCallStack
+	property alias vmCallStack: callStack
+	property alias vmStorage: storage
+	property alias vmMemory: memoryDump
+	property alias vmCallData: callDataDump
 	signal debugExecuteLocation(string documentId, var location)
 	property string compilationErrorMessage
 	property bool assemblyMode: false
diff --git a/mix/test/qml/TestMain.qml b/mix/test/qml/TestMain.qml
index d1d962900..ef1af0c53 100644
--- a/mix/test/qml/TestMain.qml
+++ b/mix/test/qml/TestMain.qml
@@ -76,6 +76,8 @@ TestCase
 	function test_dbg_transactionWithParameter() { TestDebugger.test_transactionWithParameter(); }
 	function test_dbg_constructorParameters() { TestDebugger.test_constructorParameters(); }
 	function test_dbg_arrayParametersAndStorage() { TestDebugger.test_arrayParametersAndStorage(); }
+	function test_dbg_solidity() { TestDebugger.test_solidityDebugging(); }
+	function test_dbg_vm() { TestDebugger.test_vmDebugging(); }
 	function test_miner_getDefaultiner() { TestMiner.test_getDefaultMiner(); }
 	function test_miner_selectMiner() { TestMiner.test_selectMiner(); }
 	function test_project_contractRename() { TestProject.test_contractRename(); }
diff --git a/mix/test/qml/js/TestDebugger.js b/mix/test/qml/js/TestDebugger.js
index 747b7b76d..b5b923f45 100644
--- a/mix/test/qml/js/TestDebugger.js
+++ b/mix/test/qml/js/TestDebugger.js
@@ -137,3 +137,67 @@ function test_arrayParametersAndStorage()
 	tryCompare(mainApplication.mainContent.rightPane.solStorage.item.value, "s", "42");
 	tryCompare(mainApplication.mainContent.rightPane.solCallStack.listModel, 0, "setMV");
 }
+
+function test_solidityDebugging()
+{
+	newProject();
+	editContract(
+	"contract Contract {\r " +
+	"	function add(uint256 a, uint256 b) returns (uint256)\r " +
+	"	{\r " +
+	"		return a + b;\r " +
+	"	}\r " +
+	"	function Contract()\r " +
+	"	{\r " +
+	"		uint256 local = add(42, 34);\r " +
+	"		storage = local;\r " +
+	"	}\r " +
+	"	uint256 storage;\r " +
+	"}");
+
+	mainApplication.mainContent.startQuickDebugging();
+	if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000))
+		fail("Error running transaction");
+
+	tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 20);
+	tryCompare(mainApplication.mainContent.rightPane.debugSlider, "value", 0);
+	mainApplication.mainContent.rightPane.debugSlider.value = 13;
+	tryCompare(mainApplication.mainContent.rightPane.solCallStack.listModel, 0, "add");
+	tryCompare(mainApplication.mainContent.rightPane.solCallStack.listModel, 1, "Contract");
+	tryCompare(mainApplication.mainContent.rightPane.solLocals.item.value, "local", "0");
+	tryCompare(mainApplication.mainContent.rightPane.solStorage.item.value, "storage", undefined);
+	mainApplication.mainContent.rightPane.debugSlider.value = 19;
+	tryCompare(mainApplication.mainContent.rightPane.solLocals.item.value, "local", "76");
+	tryCompare(mainApplication.mainContent.rightPane.solStorage.item.value, "storage", "76");
+}
+
+function test_vmDebugging()
+{
+	newProject();
+	editContract(
+	"contract Contract {\r " +
+	"	function add(uint256 a, uint256 b) returns (uint256)\r " +
+	"	{\r " +
+	"		return a + b;\r " +
+	"	}\r " +
+	"	function Contract()\r " +
+	"	{\r " +
+	"		uint256 local = add(42, 34);\r " +
+	"		storage = local;\r " +
+	"	}\r " +
+	"	uint256 storage;\r " +
+	"}");
+
+	mainApplication.mainContent.startQuickDebugging();
+	if (!ts.waitForSignal(mainApplication.clientModel, "debugDataReady(QObject*)", 5000))
+		fail("Error running transaction");
+
+	mainApplication.mainContent.rightPane.assemblyMode = !mainApplication.mainContent.rightPane.assemblyMode;
+	tryCompare(mainApplication.mainContent.rightPane.debugSlider, "maximumValue", 41);
+	tryCompare(mainApplication.mainContent.rightPane.debugSlider, "value", 0);
+	mainApplication.mainContent.rightPane.debugSlider.value = 35;
+	tryCompare(mainApplication.mainContent.rightPane.vmCallStack.listModel, 0, mainApplication.clientModel.contractAddresses["Contract"].substring(2));
+	tryCompare(mainApplication.mainContent.rightPane.vmStorage.listModel, 0, "@ 0 (0x0)	 76 (0x4c)");
+	tryCompare(mainApplication.mainContent.rightPane.vmMemory.listModel, "length", 0);
+}
+
diff --git a/mix/test/qml/js/TestProject.js b/mix/test/qml/js/TestProject.js
index d81b72942..7f149eff4 100644
--- a/mix/test/qml/js/TestProject.js
+++ b/mix/test/qml/js/TestProject.js
@@ -3,6 +3,7 @@ function test_contractRename()
 	newProject();
 	tryCompare(mainApplication.mainContent.projectNavigator.sections.itemAt(0).model.get(0), "name", "Contract");
 	editContract("contract Renamed {}");
+	mainApplication.mainContent.startQuickDebugging();
 	if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000))
 		fail("Error running transaction");
 	wait(1000);

From 0d45dfabe1e5c4e974d06ed36766364d27d25541 Mon Sep 17 00:00:00 2001
From: arkpar <arkady.paronyan@gmail.com>
Date: Wed, 15 Apr 2015 12:45:31 +0200
Subject: [PATCH 3/5] auto select web preview port

---
 mix/HttpServer.cpp     | 13 ++++++++++++-
 mix/HttpServer.h       |  2 +-
 mix/qml/WebPreview.qml |  2 +-
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/mix/HttpServer.cpp b/mix/HttpServer.cpp
index bf210444b..8ceb90424 100644
--- a/mix/HttpServer.cpp
+++ b/mix/HttpServer.cpp
@@ -21,6 +21,7 @@
  */
 
 #include <memory>
+#include <random>
 #include <QTcpSocket>
 #include "HttpServer.h"
 
@@ -106,8 +107,18 @@ void HttpServer::updateListening()
 	if (this->isListening())
 		this->close();
 
-	if (!m_listen || QTcpServer::listen(QHostAddress::LocalHost, m_port))
+	if (!m_listen)
 		return;
+
+	if (!QTcpServer::listen(QHostAddress::LocalHost, m_port))
+		errorStringChanged();
+
+	if (m_port != QTcpServer::serverPort())
+	{
+		m_port = QTcpServer::serverPort();
+		emit portChanged(m_port);
+		emit urlChanged(url());
+	}
 }
 
 void HttpServer::incomingConnection(qintptr _socket)
diff --git a/mix/HttpServer.h b/mix/HttpServer.h
index add83238b..8a1e4553a 100644
--- a/mix/HttpServer.h
+++ b/mix/HttpServer.h
@@ -100,7 +100,7 @@ protected:
 
 signals:
 	void clientConnected(HttpRequest* _request);
-	void errorStringChanged(QString const& _errorString);
+	void errorStringChanged();
 	void urlChanged(QUrl const& _url);
 	void portChanged(int _port);
 	void listenChanged(bool _listen);
diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml
index 58bb3c64d..49d7095e5 100644
--- a/mix/qml/WebPreview.qml
+++ b/mix/qml/WebPreview.qml
@@ -150,7 +150,7 @@ Item {
 		id: httpServer
 		listen: true
 		accept: true
-		port: 8893
+		//port: 8893
 		onClientConnected: {
 			var urlPath = _request.url.toString();
 			if (urlPath.indexOf("/rpc/") === 0)

From 215329e1884a14bdaad1d7da31db303bafd96060 Mon Sep 17 00:00:00 2001
From: arkpar <arkady.paronyan@gmail.com>
Date: Wed, 15 Apr 2015 12:49:45 +0200
Subject: [PATCH 4/5] style

---
 mix/HttpServer.cpp     | 1 -
 mix/qml/WebPreview.qml | 1 -
 2 files changed, 2 deletions(-)

diff --git a/mix/HttpServer.cpp b/mix/HttpServer.cpp
index 8ceb90424..977008ead 100644
--- a/mix/HttpServer.cpp
+++ b/mix/HttpServer.cpp
@@ -21,7 +21,6 @@
  */
 
 #include <memory>
-#include <random>
 #include <QTcpSocket>
 #include "HttpServer.h"
 
diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml
index 49d7095e5..bd1d37e61 100644
--- a/mix/qml/WebPreview.qml
+++ b/mix/qml/WebPreview.qml
@@ -150,7 +150,6 @@ Item {
 		id: httpServer
 		listen: true
 		accept: true
-		//port: 8893
 		onClientConnected: {
 			var urlPath = _request.url.toString();
 			if (urlPath.indexOf("/rpc/") === 0)

From 59d9fb49ffae6150c82b441d9ae4f5486006e16a Mon Sep 17 00:00:00 2001
From: arkpar <arkady.paronyan@gmail.com>
Date: Wed, 15 Apr 2015 13:38:53 +0200
Subject: [PATCH 5/5] skip web preview for contracts which are not deployed yet

---
 mix/HttpServer.cpp              |  3 +++
 mix/qml/WebPreview.qml          | 13 ++++++++-----
 mix/test/qml/TestMain.qml       |  9 +++++++++
 mix/test/qml/js/TestDebugger.js |  9 +++------
 mix/test/qml/js/TestProject.js  |  3 +--
 5 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/mix/HttpServer.cpp b/mix/HttpServer.cpp
index 977008ead..968580907 100644
--- a/mix/HttpServer.cpp
+++ b/mix/HttpServer.cpp
@@ -110,7 +110,10 @@ void HttpServer::updateListening()
 		return;
 
 	if (!QTcpServer::listen(QHostAddress::LocalHost, m_port))
+	{
 		errorStringChanged();
+		return;
+	}
 
 	if (m_port != QTcpServer::serverPort())
 	{
diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml
index bd1d37e61..44f96a775 100644
--- a/mix/qml/WebPreview.qml
+++ b/mix/qml/WebPreview.qml
@@ -40,11 +40,14 @@ Item {
 		var contracts = {};
 		for (var c in codeModel.contracts) {
 			var contract = codeModel.contracts[c];
-			contracts[c] = {
-				name: contract.contract.name,
-				address: clientModel.contractAddresses[contract.contract.name],
-				interface: JSON.parse(contract.contractInterface),
-			};
+			var address = clientModel.contractAddresses[contract.contract.name];
+			if (address) {
+				contracts[c] = {
+					name: contract.contract.name,
+					address: address,
+					interface: JSON.parse(contract.contractInterface),
+				};
+			}
 		}
 		webView.runJavaScript("updateContracts(" + JSON.stringify(contracts) + ")");
 	}
diff --git a/mix/test/qml/TestMain.qml b/mix/test/qml/TestMain.qml
index ef1af0c53..73cff824e 100644
--- a/mix/test/qml/TestMain.qml
+++ b/mix/test/qml/TestMain.qml
@@ -50,12 +50,21 @@ TestCase
 
 	function editContract(c)
 	{
+		if (mainApplication.codeModel.compiling)
+			ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000);
 		mainApplication.mainContent.codeEditor.getEditor("contract.sol").setText(c);
 		if (!ts.waitForSignal(mainApplication.codeModel, "compilationComplete()", 5000))
 			fail("not compiled");
 		ts.keyPressChar(mainApplication, "S", Qt.ControlModifier, 200); //Ctrl+S
 	}
 
+
+	function waitForExecution()
+	{
+		while (mainApplication.clientModel.running)
+			ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000);
+	}
+
 	function editHtml(c)
 	{
 		mainApplication.projectModel.openDocument("index.html");
diff --git a/mix/test/qml/js/TestDebugger.js b/mix/test/qml/js/TestDebugger.js
index b5b923f45..706601d18 100644
--- a/mix/test/qml/js/TestDebugger.js
+++ b/mix/test/qml/js/TestDebugger.js
@@ -14,8 +14,7 @@ function test_defaultTransactionSequence()
 	"	uint z;\r" +
 	"}\r"
 	);
-	if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000))
-		fail("Error running transaction");
+	waitForExecution();
 	tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel, "count", 3);
 }
 
@@ -47,8 +46,7 @@ function test_transactionWithParameter()
 	transactionDialog.acceptAndClose();
 	mainApplication.projectModel.stateDialog.acceptAndClose();
 	mainApplication.mainContent.startQuickDebugging();
-	if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000))
-		fail("Error running transaction");
+	waitForExecution();
 	tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel, "count", 5);
 	tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "returned", "(442)");
 }
@@ -79,8 +77,7 @@ function test_constructorParameters()
 	transactionDialog.acceptAndClose();
 	mainApplication.projectModel.stateDialog.acceptAndClose();
 	mainApplication.mainContent.startQuickDebugging();
-	if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000))
-		fail("Error running transaction");
+	waitForExecution();
 	tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel, "count", 4);
 	tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(3), "returned", "(442)");
 }
diff --git a/mix/test/qml/js/TestProject.js b/mix/test/qml/js/TestProject.js
index 7f149eff4..444760ea3 100644
--- a/mix/test/qml/js/TestProject.js
+++ b/mix/test/qml/js/TestProject.js
@@ -4,8 +4,7 @@ function test_contractRename()
 	tryCompare(mainApplication.mainContent.projectNavigator.sections.itemAt(0).model.get(0), "name", "Contract");
 	editContract("contract Renamed {}");
 	mainApplication.mainContent.startQuickDebugging();
-	if (!ts.waitForSignal(mainApplication.clientModel, "runComplete()", 5000))
-		fail("Error running transaction");
+	waitForExecution();
 	wait(1000);
 	tryCompare(mainApplication.mainContent.projectNavigator.sections.itemAt(0).model.get(0), "name", "Renamed");
 	mainApplication.projectModel.stateListModel.editState(0);