Skip to content

Commit

Permalink
Add an automated test
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioarnold committed Jun 17, 2022
1 parent 340597f commit 4636e56
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 16 deletions.
8 changes: 8 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
"console": "internalConsole",
"internalConsoleOptions": "neverOpen",
"preLaunchTask": "build"
},
{
"name": "(Windows) Launch automated test",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceRoot}/zig-out/bin/minipixel.exe",
"cwd": "${workspaceFolder}",
"preLaunchTask": "build automated test"
}
]
}
7 changes: 7 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
"showReuseMessage": false,
"clear": true
}
},
{
"label": "build automated test",
"type": "shell",
"command": "zig",
"args": ["build", "-Dautomated-testing=true", "-Drelease-fast=true"],
"group": "build"
}
]
}
6 changes: 6 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@ fn installPalFiles(b: *Builder) void {
pub fn build(b: *Builder) !void {
const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions();
const automated_testing = b.option(bool, "automated-testing", "Enable automated testing") orelse false;

const exe = b.addExecutable("minipixel", "src/main.zig");
exe.setBuildMode(mode);
exe.setTarget(target);

const exe_options = b.addOptions();
exe.addOptions("build_options", exe_options);
exe_options.addOption(bool, "automated_testing", automated_testing);

// exe.addIncludeDir("lib/nanovg/src");
exe.addIncludeDir("lib/gl2/include");
if (exe.target.isWindows()) {
Expand Down
2 changes: 1 addition & 1 deletion deps/s2s
Submodule s2s updated 1 files
+24 −8 s2s.zig
16 changes: 11 additions & 5 deletions src/CanvasWidget.zig
Original file line number Diff line number Diff line change
Expand Up @@ -548,10 +548,14 @@ const DrawTool = struct {
self.last_point = null;
}

fn onMouseMove(self: *DrawTool, canvas: *CanvasWidget, event: *const gui.MouseEvent) void {
const point = canvas.toDocumentSpace(event.x, event.y);
fn updateEditPoint(self: *DrawTool, canvas: *CanvasWidget, event_x: f32, event_y: f32) void {
const point = canvas.toDocumentSpace(event_x, event_y);
self.edit_point.x = @floatToInt(i32, @floor(point.x));
self.edit_point.y = @floatToInt(i32, @floor(point.y));
}

fn onMouseMove(self: *DrawTool, canvas: *CanvasWidget, event: *const gui.MouseEvent) void {
self.updateEditPoint(canvas, event.x, event.y);

if (event.isButtonPressed(.left) and self.drawing) {
if (self.last_point) |last_point| {
Expand Down Expand Up @@ -580,6 +584,8 @@ const DrawTool = struct {
}

fn onMouseDown(self: *DrawTool, canvas: *CanvasWidget, event: *const gui.MouseEvent) void {
self.updateEditPoint(canvas, event.x, event.y);

if (event.button == .left) {
if (event.isModifierPressed(.shift) and self.last_point != null) {
if (self.last_point) |last_point| {
Expand All @@ -602,6 +608,8 @@ const DrawTool = struct {
}

fn onMouseUp(self: *DrawTool, canvas: *CanvasWidget, event: *const gui.MouseEvent) void {
self.updateEditPoint(canvas, event.x, event.y);

if (event.button == .left) {
canvas.document.endStroke() catch {}; // TODO: show error message
self.drawing = false;
Expand Down Expand Up @@ -655,9 +663,7 @@ const DrawTool = struct {
}

fn updateMousePreview(self: *DrawTool, canvas: *CanvasWidget, mouse_x: f32, mouse_y: f32) void {
const point = canvas.toDocumentSpace(mouse_x, mouse_y);
self.edit_point.x = @floatToInt(i32, @floor(point.x));
self.edit_point.y = @floatToInt(i32, @floor(point.y));
self.updateEditPoint(canvas, mouse_x, mouse_y);
canvas.document.previewBrush(self.edit_point.x, self.edit_point.y);
}

Expand Down
60 changes: 60 additions & 0 deletions src/automated_testing.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const std = @import("std");
const nextFrame = @import("main.zig").automatedTestLoopIteration;
const gui = @import("gui");
const EditorWidget = @import("EditorWidget.zig");

fn mouseLeftDown(window: *gui.Window, x: f32, y: f32) void {
var me = gui.MouseEvent{
.event = .{ .type = .MouseDown },
.button = .left,
.click_count = 0,
.state = 1,
.modifiers = 0,
.x = x,
.y = y,
.wheel_x = 0,
.wheel_y = 0,
};
window.handleEvent(&me.event);
}

fn mouseLeftUp(window: *gui.Window, x: f32, y: f32) void {
var me = gui.MouseEvent{
.event = .{ .type = .MouseUp },
.button = .left,
.click_count = 0,
.state = 1,
.modifiers = 0,
.x = x,
.y = y,
.wheel_x = 0,
.wheel_y = 0,
};
window.handleEvent(&me.event);
}

pub fn runTests(window: *gui.Window) !void {
var editor_widget = @fieldParentPtr(EditorWidget, "widget", window.main_widget.?);
try testCanSetIndividualPixels(window, editor_widget);
}

fn testCanSetIndividualPixels(window: *gui.Window, editor_widget: *EditorWidget) !void {
// Setup
try editor_widget.createNewDocument(1024, 1024, .color);
editor_widget.canvas.scale = 1;
editor_widget.canvas.translation.x = 0;
editor_widget.canvas.translation.y = 0;
const canvas_rect = editor_widget.canvas.widget.relative_rect;

var y: f32 = 0;
while (y < 16) : (y += 1) {
var x: f32 = 0;
while (x < 16) : (x += 1) {
const mx = canvas_rect.x + x;
const my = canvas_rect.y + y;
mouseLeftDown(window, mx, my);
mouseLeftUp(window, mx, my);
nextFrame();
}
}
}
39 changes: 29 additions & 10 deletions src/main.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
const build_options = @import("build_options");
const win32 = @import("win32");
const foundation = win32.foundation;
const windows = win32.ui.windows_and_messaging;
Expand All @@ -14,6 +15,7 @@ const Clipboard = @import("Clipboard.zig");
const EditorWidget = @import("EditorWidget.zig");
const MessageBoxWidget = @import("MessageBoxWidget.zig");
const info = @import("info.zig");
const automated_testing = @import("automated_testing.zig");

extern fn gladLoadGL() callconv(.C) c_int; // init OpenGL function pointers on Windows and Linux
extern fn SetProcessDPIAware() callconv(.C) c_int;
Expand Down Expand Up @@ -733,15 +735,16 @@ fn sdlHandleEvent(sdl_event: c.SDL_Event) void {
}

const MainloopType = enum {
waitEvent, // updates only when an event occurs
regularInterval, // runs at monitor refresh rate
wait_event, // updates only when an event occurs
regular_interval, // runs at monitor refresh rate
};
var mainloop_type: MainloopType = .waitEvent;
var mainloop_type: MainloopType = .wait_event;

var gpa = std.heap.GeneralPurposeAllocator(.{
.enable_memory_limit = true,
}){};

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{
.enable_memory_limit = true,
}){};
defer {
if (builtin.mode == .Debug) {
const leaked = gpa.deinit();
Expand Down Expand Up @@ -806,7 +809,7 @@ pub fn main() !void {
// }

if (builtin.os.tag == .linux or builtin.os.tag == .macos or true) {
mainloop_type = .regularInterval;
mainloop_type = .regular_interval;
_ = c.SDL_GL_SetSwapInterval(0); // disable VSync
}

Expand Down Expand Up @@ -844,27 +847,43 @@ pub fn main() !void {
}
std.process.argsFree(allocator, args);

if (build_options.automated_testing) {
main_window.onCloseRequestFn = null;
try automated_testing.runTests(main_window);
main_window.close();
return;
}

// quit app when there are no more windows open
while (app.windows.items.len > 0) {
var sdl_event: c.SDL_Event = undefined;
switch (mainloop_type) {
.waitEvent => if (c.SDL_WaitEvent(&sdl_event) == 0) {
.wait_event => if (c.SDL_WaitEvent(&sdl_event) == 0) {
c.SDL_Log("SDL_WaitEvent failed: %s", c.SDL_GetError());
} else {
sdlHandleEvent(sdl_event);
},
.regularInterval => while (c.SDL_PollEvent(&sdl_event) != 0) {
.regular_interval => while (c.SDL_PollEvent(&sdl_event) != 0) {
sdlHandleEvent(sdl_event);
},
}

editor_widget.setMemoryUsageInfo(gpa.total_requested_bytes);
for (sdl_windows.items) |*sdl_window| {
if (sdl_window.dirty) sdl_window.draw();
if (sdl_window.dirty or mainloop_type == .regular_interval) sdl_window.draw();
}
}
}

pub fn automatedTestLoopIteration() void {
var sdl_event: c.SDL_Event = undefined;
while (c.SDL_PollEvent(&sdl_event) != 0) {}
editor_widget.setMemoryUsageInfo(gpa.total_requested_bytes);
for (sdl_windows.items) |*sdl_window| {
sdl_window.draw();
}
}

fn onMainWindowCloseRequest(context: usize) bool {
if (editor_widget.has_unsaved_changes) {
editor_widget.showUnsavedChangesDialog(onUnsavedChangesDialogResult, context);
Expand Down

0 comments on commit 4636e56

Please sign in to comment.