-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_functionality.ml
More file actions
356 lines (292 loc) · 12.7 KB
/
Copy pathtest_functionality.ml
File metadata and controls
356 lines (292 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
(*
* Test module for P2P Whiteboard functionality
* This module tests core functionality without the complex UI dependencies
*)
(* Core test modules that can be compiled without the full UI stack *)
module TestConfig = struct
type config = {
port : int;
multicast_group : string;
canvas_width : int;
canvas_height : int;
bridge_mode : bool;
}
let default_config = {
port = 8080;
multicast_group = "239.0.0.1";
canvas_width = 80;
canvas_height = 30;
bridge_mode = false;
}
let create_test_config port =
{ default_config with port }
end
module TestNetwork = struct
type peer_id = string
type message_type =
| Discover
| Canvas_update of string * int * int
| Chat_message of string * string
type peer = {
id : peer_id;
address : string;
port : int;
last_seen : float;
}
type network_state = {
peers : (peer_id, peer) Hashtbl.t;
local_id : peer_id;
config : TestConfig.config;
mutable message_log : (peer_id * message_type * float) list;
}
let create_network_state config =
let local_id = Printf.sprintf "test_peer_%d" (Random.int 10000) in
{
peers = Hashtbl.create 16;
local_id;
config;
message_log = [];
}
let add_peer state peer_id address port =
let peer = {
id = peer_id;
address;
port;
last_seen = Unix.time ();
} in
Hashtbl.replace state.peers peer_id peer;
Printf.printf "Added peer: %s at %s:%d\n" peer_id address port
let simulate_message state from_peer msg =
let timestamp = Unix.time () in
state.message_log <- (from_peer, msg, timestamp) :: state.message_log;
match msg with
| Discover ->
Printf.printf "Received discovery from %s\n" from_peer
| Canvas_update (data, x, y) ->
Printf.printf "Received canvas update from %s: %s at (%d,%d)\n" from_peer data x y
| Chat_message (user, message) ->
Printf.printf "Received chat from %s: %s: %s\n" from_peer user message
let get_peer_count state = Hashtbl.length state.peers
let get_message_count state = List.length state.message_log
end
module TestCanvas = struct
type color = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White
type drawing_char = {
char : char;
color : color;
user_id : string;
}
type canvas = {
width : int;
height : int;
cells : drawing_char option array array;
mutable cursor_x : int;
mutable cursor_y : int;
}
let create_canvas width height =
{
width;
height;
cells = Array.make_matrix height width None;
cursor_x = 0;
cursor_y = 0;
}
let set_char canvas x y char color user_id =
if x >= 0 && x < canvas.width && y >= 0 && y < canvas.height then (
canvas.cells.(y).(x) <- Some { char; color; user_id };
true
) else false
let get_char canvas x y =
if x >= 0 && x < canvas.width && y >= 0 && y < canvas.height then
canvas.cells.(y).(x)
else
None
let move_cursor canvas dx dy =
let new_x = max 0 (min (canvas.width - 1) (canvas.cursor_x + dx)) in
let new_y = max 0 (min (canvas.height - 1) (canvas.cursor_y + dy)) in
canvas.cursor_x <- new_x;
canvas.cursor_y <- new_y;
(new_x, new_y)
let draw_pixel canvas char color user_id =
set_char canvas canvas.cursor_x canvas.cursor_y char color user_id
let clear_canvas canvas =
for y = 0 to canvas.height - 1 do
for x = 0 to canvas.width - 1 do
canvas.cells.(y).(x) <- None
done
done
let count_drawn_pixels canvas =
let count = ref 0 in
for y = 0 to canvas.height - 1 do
for x = 0 to canvas.width - 1 do
match canvas.cells.(y).(x) with
| Some _ -> incr count
| None -> ()
done
done;
!count
let canvas_to_string canvas =
let buffer = Buffer.create (canvas.width * canvas.height) in
for y = 0 to canvas.height - 1 do
for x = 0 to canvas.width - 1 do
match canvas.cells.(y).(x) with
| Some { char; _ } -> Buffer.add_char buffer char
| None -> Buffer.add_char buffer ' '
done;
if y < canvas.height - 1 then Buffer.add_char buffer '\n'
done;
Buffer.contents buffer
end
(* Test functions for multi-user scenarios *)
let test_dual_user_setup () =
Printf.printf "\n=== Testing Dual User Setup ===\n";
Random.self_init ();
(* Create two user configurations *)
let config1 = TestConfig.create_test_config 8080 in
let config2 = TestConfig.create_test_config 8080 in
(* Create network states for both users *)
let user1_network = TestNetwork.create_network_state config1 in
let user2_network = TestNetwork.create_network_state config2 in
Printf.printf "User 1 ID: %s\n" user1_network.local_id;
Printf.printf "User 2 ID: %s\n" user2_network.local_id;
(* Simulate peer discovery *)
TestNetwork.add_peer user1_network user2_network.local_id "127.0.0.1" 8080;
TestNetwork.add_peer user2_network user1_network.local_id "127.0.0.1" 8080;
(* Test messaging between peers *)
TestNetwork.simulate_message user1_network user2_network.local_id TestNetwork.Discover;
TestNetwork.simulate_message user2_network user1_network.local_id (TestNetwork.Chat_message ("User2", "Hello from User 2!"));
TestNetwork.simulate_message user1_network user2_network.local_id (TestNetwork.Chat_message ("User1", "Hello back from User 1!"));
(* Verify connections *)
let user1_peers = TestNetwork.get_peer_count user1_network in
let user2_peers = TestNetwork.get_peer_count user2_network in
let user1_messages = TestNetwork.get_message_count user1_network in
let user2_messages = TestNetwork.get_message_count user2_network in
Printf.printf "User 1 connected peers: %d\n" user1_peers;
Printf.printf "User 2 connected peers: %d\n" user2_peers;
Printf.printf "User 1 received messages: %d\n" user1_messages;
Printf.printf "User 2 received messages: %d\n" user2_messages;
(* Test results *)
let success = user1_peers = 1 && user2_peers = 1 && user1_messages >= 1 && user2_messages >= 1 in
Printf.printf "Dual user setup test: %s\n" (if success then "PASSED" else "FAILED");
success
let test_collaborative_drawing () =
Printf.printf "\n=== Testing Collaborative Drawing ===\n";
(* Create shared canvas *)
let canvas = TestCanvas.create_canvas 20 10 in
(* Simulate User 1 drawing *)
Printf.printf "User 1 drawing...\n";
TestCanvas.move_cursor canvas 5 5 |> ignore;
let drawn1 = TestCanvas.draw_pixel canvas 'X' TestCanvas.Red "user1" in
TestCanvas.move_cursor canvas 1 0 |> ignore;
let drawn2 = TestCanvas.draw_pixel canvas 'O' TestCanvas.Blue "user1" in
(* Simulate User 2 drawing *)
Printf.printf "User 2 drawing...\n";
TestCanvas.move_cursor canvas 2 2 |> ignore;
let drawn3 = TestCanvas.draw_pixel canvas '*' TestCanvas.Green "user2" in
TestCanvas.move_cursor canvas 10 8 |> ignore;
let drawn4 = TestCanvas.draw_pixel canvas '#' TestCanvas.Yellow "user2" in
(* Check canvas state *)
let pixel_count = TestCanvas.count_drawn_pixels canvas in
Printf.printf "Total pixels drawn: %d\n" pixel_count;
(* Verify specific drawings *)
let char_at_5_5 = TestCanvas.get_char canvas 5 5 in
let char_at_6_5 = TestCanvas.get_char canvas 6 5 in
let char_at_2_2 = TestCanvas.get_char canvas 2 2 in
let char_at_10_8 = TestCanvas.get_char canvas 10 8 in
Printf.printf "Character at (5,5): %s\n"
(match char_at_5_5 with Some {char; user_id; _} -> Printf.sprintf "'%c' by %s" char user_id | None -> "empty");
Printf.printf "Character at (6,5): %s\n"
(match char_at_6_5 with Some {char; user_id; _} -> Printf.sprintf "'%c' by %s" char user_id | None -> "empty");
Printf.printf "Character at (2,2): %s\n"
(match char_at_2_2 with Some {char; user_id; _} -> Printf.sprintf "'%c' by %s" char user_id | None -> "empty");
Printf.printf "Character at (10,8): %s\n"
(match char_at_10_8 with Some {char; user_id; _} -> Printf.sprintf "'%c' by %s" char user_id | None -> "empty");
(* Test synchronization simulation *)
Printf.printf "\nSimulating network synchronization...\n";
let user1_network = TestNetwork.create_network_state (TestConfig.create_test_config 8080) in
let user2_network = TestNetwork.create_network_state (TestConfig.create_test_config 8080) in
TestNetwork.simulate_message user2_network user1_network.local_id (TestNetwork.Canvas_update ("X", 5, 5));
TestNetwork.simulate_message user1_network user2_network.local_id (TestNetwork.Canvas_update ("*", 2, 2));
let success = drawn1 && drawn2 && drawn3 && drawn4 && pixel_count = 4 in
Printf.printf "Collaborative drawing test: %s\n" (if success then "PASSED" else "FAILED");
success
let test_canvas_operations () =
Printf.printf "\n=== Testing Canvas Operations ===\n";
let canvas = TestCanvas.create_canvas 10 10 in
(* Test cursor movement *)
let (x1, y1) = TestCanvas.move_cursor canvas 3 4 in
Printf.printf "Moved cursor to: (%d,%d)\n" x1 y1;
(* Test boundary conditions *)
let (x2, y2) = TestCanvas.move_cursor canvas 100 100 in
Printf.printf "Moved cursor to boundary: (%d,%d)\n" x2 y2;
let (x3, y3) = TestCanvas.move_cursor canvas (-100) (-100) in
Printf.printf "Moved cursor to boundary: (%d,%d)\n" x3 y3;
(* Test drawing and clearing *)
TestCanvas.move_cursor canvas 5 5 |> ignore;
let drawn = TestCanvas.draw_pixel canvas 'T' TestCanvas.Cyan "test_user" in
let count_before = TestCanvas.count_drawn_pixels canvas in
TestCanvas.clear_canvas canvas;
let count_after = TestCanvas.count_drawn_pixels canvas in
Printf.printf "Pixels before clear: %d\n" count_before;
Printf.printf "Pixels after clear: %d\n" count_after;
let success = x1 = 3 && y1 = 4 && x2 = 9 && y2 = 9 && x3 = 0 && y3 = 0 &&
drawn && count_before = 1 && count_after = 0 in
Printf.printf "Canvas operations test: %s\n" (if success then "PASSED" else "FAILED");
success
let create_demo_canvas () =
Printf.printf "\n=== Creating Demo Canvas ===\n";
let canvas = TestCanvas.create_canvas 30 15 in
(* User 1 draws a simple house *)
Printf.printf "User 1 drawing a house...\n";
TestCanvas.move_cursor canvas 5 10 |> ignore;
TestCanvas.draw_pixel canvas '/' TestCanvas.Red "user1" |> ignore;
TestCanvas.move_cursor canvas 1 0 |> ignore;
TestCanvas.draw_pixel canvas '\\' TestCanvas.Red "user1" |> ignore;
TestCanvas.move_cursor canvas (-1) 1 |> ignore;
TestCanvas.draw_pixel canvas '|' TestCanvas.Blue "user1" |> ignore;
TestCanvas.move_cursor canvas 0 1 |> ignore;
TestCanvas.draw_pixel canvas '|' TestCanvas.Blue "user1" |> ignore;
TestCanvas.move_cursor canvas 0 1 |> ignore;
TestCanvas.draw_pixel canvas '-' TestCanvas.Blue "user1" |> ignore;
TestCanvas.move_cursor canvas 1 0 |> ignore;
TestCanvas.draw_pixel canvas '-' TestCanvas.Blue "user1" |> ignore;
(* User 2 adds decorations *)
Printf.printf "User 2 adding decorations...\n";
TestCanvas.move_cursor canvas 10 5 |> ignore;
TestCanvas.draw_pixel canvas '*' TestCanvas.Yellow "user2" |> ignore;
TestCanvas.move_cursor canvas 15 8 |> ignore;
TestCanvas.draw_pixel canvas 'o' TestCanvas.Green "user2" |> ignore;
TestCanvas.move_cursor canvas 20 12 |> ignore;
TestCanvas.draw_pixel canvas '~' TestCanvas.Cyan "user2" |> ignore;
let pixel_count = TestCanvas.count_drawn_pixels canvas in
Printf.printf "Total collaborative pixels: %d\n" pixel_count;
(* Display a portion of the canvas *)
Printf.printf "\nDemo canvas preview (first 10 lines):\n";
Printf.printf "%s\n" (String.sub (TestCanvas.canvas_to_string canvas) 0 (min 300 (String.length (TestCanvas.canvas_to_string canvas))));
pixel_count > 0
let run_all_tests () =
Printf.printf "P2P Whiteboard Functionality Tests\n";
Printf.printf "===================================\n";
let test1 = test_dual_user_setup () in
let test2 = test_collaborative_drawing () in
let test3 = test_canvas_operations () in
let test4 = create_demo_canvas () in
Printf.printf "\n=== Test Results Summary ===\n";
Printf.printf "Dual User Setup: %s\n" (if test1 then "PASSED" else "FAILED");
Printf.printf "Collaborative Drawing: %s\n" (if test2 then "PASSED" else "FAILED");
Printf.printf "Canvas Operations: %s\n" (if test3 then "PASSED" else "FAILED");
Printf.printf "Demo Canvas: %s\n" (if test4 then "PASSED" else "FAILED");
let all_passed = test1 && test2 && test3 && test4 in
Printf.printf "\nOverall Result: %s\n" (if all_passed then "ALL TESTS PASSED" else "SOME TESTS FAILED");
if all_passed then
Printf.printf "\n✓ The P2P Whiteboard application core functionality is working correctly!\n"
else
Printf.printf "\n✗ Some core functionality tests failed. Check implementation.\n";
all_passed
(* Main function *)
let () =
let success = run_all_tests () in
if success then
exit 0
else
exit 1