Skip to content

Commit

Permalink
Merge pull request #12 from Shubh942/master2
Browse files Browse the repository at this point in the history
Added gdb Components with functionality of uploading file in server
  • Loading branch information
Ammoniya authored Jun 25, 2024
2 parents d85f565 + 36a43d6 commit 3e73aab
Show file tree
Hide file tree
Showing 50 changed files with 581 additions and 82 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/run-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ jobs:
python-version: "3.10"

- name: Install gdb
run: sudo apt-get install -y gdb
run: |
sudo apt-get update
sudo apt-get install -y gdb
- name: Install dependencies
run: |
Expand Down
97 changes: 88 additions & 9 deletions gdbui_server/flask_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import tempfile
from flask import Flask
from flask_testing import TestCase
from unittest import mock
from io import BytesIO
from main import app
import os

class TestGDBRoutes(TestCase):
def create_app(self):
Expand All @@ -22,15 +25,36 @@ def setUp(self):
def tearDown(self):
self.temp_dir.cleanup()


def test_compile_code(self):
payload = {
"code": "#include <iostream>\nint main() { std::cout << 'Hello, Universe!'; return 0; }",
"name": f"{self.temp_dir.name}/test_program2",
}
response = self.client.post('/compile', data=json.dumps(payload), content_type='application/json')

self.assertEqual(response.status_code, 200)
self.assertTrue(response.json['success'])
with mock.patch('os.makedirs') as mock_makedirs:
with mock.patch.object(self.client, 'post') as mock_post:

mock_response = mock.Mock()
mock_response.status_code = 200
mock_response.json = {'output': 'Compilation successful', 'success': True}
mock_post.return_value = mock_response

output_dir = os.path.join(self.temp_dir.name, 'output')

if not os.path.exists(output_dir):
os.makedirs(output_dir)

rel_output_dir = os.path.relpath(output_dir, self.temp_dir.name)
rel_output_dir = rel_output_dir.replace("\\", "/")

payload = {
"code": '#include <iostream>\nint main() { std::cout << "Hello, Universe!"; return 0; }',
"name": f"test_program2",
}

response = self.client.post('/compile', data=json.dumps(payload), content_type='application/json')

self.assertEqual(response.status_code, 200)
self.assertTrue(response.json['success'])

mock_makedirs.assert_called_with(output_dir)


def test_gdb_command(self):
gdb_payload = {
Expand Down Expand Up @@ -167,6 +191,61 @@ def test_delete_breakpoint(self):
response = self.client.post('/delete_breakpoint', data=json.dumps(delete_breakpoint_payload), content_type='application/json')
self.assertEqual(response.status_code, 200)
self.assertTrue(response.json['success'])

@mock.patch('werkzeug.datastructures.FileStorage.save')
def test_upload_file(self, mock_save):
data = {
'file': (BytesIO(b"dummy file content"), 'test_program'),
'name': 'test_program'
}

response = self.client.post('/upload_file', content_type='multipart/form-data', data=data)

response_data = json.loads(response.data)
self.assertEqual(response.status_code, 200)
self.assertTrue(response_data['success'])
self.assertIn('File uploaded successfully', response_data['message'])

mock_save.assert_called_once()

expected_path = 'output/test_program.exe'
self.assertEqual(response_data['file_path'], expected_path)

@mock.patch('werkzeug.datastructures.FileStorage.save')
def test_upload_file_no_file(self, mock_save):

data = {'name': 'test_program'}
response = self.client.post('/upload_file', content_type='multipart/form-data', data=data)

response_data = json.loads(response.data)
self.assertEqual(response.status_code, 400)
self.assertFalse(response_data['success'])
self.assertIn('No file or name provided', response_data['error'])

@mock.patch('werkzeug.datastructures.FileStorage.save')
def test_upload_file_no_name(self, mock_save):

data = {'file': (BytesIO(b"dummy file content"), 'test_program')}
response = self.client.post('/upload_file', content_type='multipart/form-data', data=data)

response_data = json.loads(response.data)
self.assertEqual(response.status_code, 400)
self.assertFalse(response_data['success'])
self.assertIn('No file or name provided', response_data['error'])

@mock.patch('werkzeug.datastructures.FileStorage.save')
def test_upload_file_empty_filename(self, mock_save):

data = {
'file': (BytesIO(b"dummy file content"), ''),
'name': 'test_program'
}
response = self.client.post('/upload_file', content_type='multipart/form-data', data=data)

response_data = json.loads(response.data)
self.assertEqual(response.status_code, 400)
self.assertFalse(response_data['success'])
self.assertIn('No selected file', response_data['error'])

if __name__ == '__main__':
unittest.main()
unittest.main()
28 changes: 24 additions & 4 deletions gdbui_server/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from pygdbmi.gdbcontroller import GdbController
from flask_cors import CORS
import subprocess
import os

app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'

# Initialize global variables to store the GDB controller and program name
gdb_controller = None
program_name = None

Expand All @@ -20,6 +20,9 @@ def execute_gdb_command(command):
strm = strm + "\n " + str(rem.get('payload'))
return strm.strip()

def ensure_exe_extension(name):
return name if name.endswith('.exe') else name + '.exe'

def start_gdb_session(program):
global gdb_controller, program_name
program_name = program
Expand All @@ -29,12 +32,12 @@ def start_gdb_session(program):
raise RuntimeError(f"Failed to initialize GDB controller: {e}")

try:
response = gdb_controller.write(f"-file-exec-and-symbols {program_name}.exe")
response = gdb_controller.write(f"-file-exec-and-symbols {os.path.join('output/', ensure_exe_extension(program_name))}")
if response is None:
raise RuntimeError("No response from GDB controller")
except Exception as e:
raise RuntimeError(f"Failed to set program file: {e}")

try:
response = gdb_controller.write("run")
if response is None:
Expand Down Expand Up @@ -77,14 +80,31 @@ def compile_code():
with open(f'{name}.cpp', 'w') as file:
file.write(code)

result = subprocess.run(['g++', f'{name}.cpp', '-o', f'{name}.exe'], capture_output=True, text=True)
result = subprocess.run(['g++', f'{name}.cpp', '-o', f'output/{name}.exe'], capture_output=True, text=True)

if result.returncode == 0:
program_name = None
return jsonify({'success': True, 'output': 'Compilation successful.'})
else:
return jsonify({'success': False, 'output': result.stderr})

@app.route('/upload_file', methods=['POST'])
def upload_file():
if 'file' not in request.files or 'name' not in request.form:
return jsonify({'success': False, 'error': 'No file or name provided'}), 400

file = request.files['file']
name = request.form['name']

if file.filename == '':
return jsonify({'success': False, 'error': 'No selected file'}), 400

file_path = os.path.join('output/', ensure_exe_extension(name))
file.save(file_path)

return jsonify({'success': True, 'message': 'File uploaded successfully', 'file_path': file_path})


@app.route('/set_breakpoint', methods=['POST'])
def set_breakpoint():
global program_name
Expand Down
Binary file added gdbui_server/output/program.exe
Binary file not shown.
14 changes: 0 additions & 14 deletions src/App.jsx

This file was deleted.

8 changes: 0 additions & 8 deletions src/components/GdbComponents/GdbComponents.css

This file was deleted.

13 changes: 0 additions & 13 deletions src/components/GdbComponents/GdbComponents.jsx

This file was deleted.

5 changes: 0 additions & 5 deletions src/components/Terminal/Terminal.css

This file was deleted.

27 changes: 0 additions & 27 deletions src/components/Terminal/TerminalComp.jsx

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
25 changes: 25 additions & 0 deletions webapp/src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";
import { Route, Routes } from "react-router-dom";
import Debug from "./pages/Debug/Debug";
import Threads from "./components/GdbComponents/Threads/Threads";
import LocalVariable from "./components/GdbComponents/LocalVariable/LocalVariable";
import Context from "./components/GdbComponents/Context/Context";
import MemoryMap from "./components/GdbComponents/MemoryMap/MemoryMap";
import BreakPoints from "./components/GdbComponents/BreakPoints/BreakPoints";

const App = () => {
return (
<Routes>
<Route path="debug" element={<Debug />}>
<Route path="threads" element={<Threads />} />
<Route path="localVariable" element={<LocalVariable />} />
<Route path="context" element={<Context />} />
<Route path="memoryMap" element={<MemoryMap />} />
<Route path="breakPoints" element={<BreakPoints />} />
</Route>
{/* You can add more routes here */}
</Routes>
);
};

export default App;
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions webapp/src/components/GdbComponents/BreakPoints/BreakPoints.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.breakpoints {
display: flex;
width: 644px;
height: 177px;
padding: 15px 20px;
flex-direction: column;
align-items: flex-start;
gap: 10px;

border: 1px solid var(--Gray-2, #4f4f4f);
background: #1e1e1e;
overflow-y: scroll;
}
43 changes: 43 additions & 0 deletions webapp/src/components/GdbComponents/BreakPoints/BreakPoints.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react";
import "./BreakPoints.css";

const data = [
{
offset: "0x2fffa36f603112ffff34",
addr: "/Users/shubh/lib/node_modules/@stdlib/math/docs/t.js:18",
},
{
offset: "0x2fffa36f603112ffff34",
addr: "/Users/shubh/lib/node_modules/@stdlib/math/docs/t.js:18",
},
{
offset: "0x2fffa36f603112ffff34",
addr: "/Users/shubh/lib/node_modules/@stdlib/math/docs/t.js:18",
},
{
offset: "0x2fffa36f603112ffff34",
addr: "/Users/shubh/lib/node_modules/@stdlib/math/docs/t.js:18",
},
];

const BreakPoints = () => {
return (
<div>
BreakPoints
<div className="breakpoints">
{data?.length > 0
? data.map((obj) => {
return (
<div>
<div>{obj.offset}</div>
<div>{obj.addr}</div>
</div>
);
})
: ""}
</div>
</div>
);
};

export default BreakPoints;
12 changes: 12 additions & 0 deletions webapp/src/components/GdbComponents/Context/Context.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.context {
display: flex;
width: 644px;
height: 177px;
padding: 15px 20px;
flex-direction: column;
align-items: flex-start;
gap: 10px;

border: 1px solid var(--Gray-2, #4f4f4f);
background: #1e1e1e;
}
Loading

0 comments on commit 3e73aab

Please sign in to comment.