diff options
author | Ibrahim Mkusa <ibrahimmkusa@gmail.com> | 2017-04-09 22:37:50 -0400 |
---|---|---|
committer | Ibrahim Mkusa <ibrahimmkusa@gmail.com> | 2017-04-09 22:37:50 -0400 |
commit | cb381871d518077649be6272af823dabec2fcd28 (patch) | |
tree | 98547efe9389421f9f58219a8278e166d2b069c6 /tests | |
parent | 404f3d7edfe648dc3fd51c1afc1b3984557f1902 (diff) |
reorganized repo a bit better
Diffstat (limited to 'tests')
-rw-r--r-- | tests/gui/Gui_Exploration.rkt | 129 | ||||
-rw-r--r-- | tests/gui/windows.rkt | 9 | ||||
-rw-r--r-- | tests/gui/windows2.rkt | 15 | ||||
-rw-r--r-- | tests/tcpevents/README.md | 1 | ||||
-rw-r--r-- | tests/tcpevents/crpovertcp.rkt | 155 | ||||
-rw-r--r-- | tests/tcpevents/server.rkt | 39 | ||||
-rw-r--r-- | tests/tcpvanilla/README.md | 20 | ||||
-rw-r--r-- | tests/tcpvanilla/client.rkt | 72 | ||||
-rw-r--r-- | tests/tcpvanilla/client2.rkt | 43 | ||||
-rw-r--r-- | tests/tcpvanilla/server.rkt | 58 | ||||
-rw-r--r-- | tests/tcpvanilla/tcptalk.rkt | 30 |
11 files changed, 571 insertions, 0 deletions
diff --git a/tests/gui/Gui_Exploration.rkt b/tests/gui/Gui_Exploration.rkt new file mode 100644 index 0000000..ff4d2d3 --- /dev/null +++ b/tests/gui/Gui_Exploration.rkt @@ -0,0 +1,129 @@ +#lang racket +(require racket/gui/base) +;;Step 1. Create a window to draw into +(define frame(new frame% [label "Example"])) +;;I don't know what frame% means, but new must be a procedure +;;(send frame show #t) Running this command displays the frame +;;send appears to be a command to be a procedure that takes a frame +;; followed by a command and a boolean. +;;the boolean is fed into the command in this case +;;if you said #f it would close the window +;;that is usefull +;;Below is a slight expantion on example code +;;letting the button be a toggle +(define frame2 (new frame%[label "Example2"])) +(define msg (new message% [parent frame2] [label " Nothing "])) +(define thingy #t) +(define button-to-click (new button% + [parent frame2] + [label "Click"] + [callback (lambda (button event) + (if thingy + (begin (set! thingy #f) + (send msg set-label "Something")) + (begin (set! thingy #t) + (send msg set-label " Nothing "))))])) +;;Frames are okay ish for error messages but the real stuff is +;;in canvas stuff +(define my-canvas% + (class canvas% + (define/override (on-event event) + (send msg set-label "Canvas mouse")) + (define/override (on-char event) + (send msg set-label "Canvas keyboard")) + (super-new)));;Don't know what that one means + +(define canvas-thing (new my-canvas% [parent frame2]));;unfortunately +;;we still need to re-size it manually +;;Now I wonder if we could create a procedure to make any text +;;appear +(define frame3 (new frame%[label "Example3"])) +(define blank (new message% [parent frame3] [label " "])) +(define (make-text string) (begin (send blank set-label string))) +;(send frame3 show #t) +;(make-text "Hello World") works exactly fine. +;;Now lets do something more complicated +;;We want to create a procedure that creates a new line +;;each time it is called so... +(define frame4 (new frame%[label "Example4"])) +;;now blank4 should be a procedure to create multiple lines in the frame +(define (make-text-line string) (begin (new message% + [parent frame4] + [label string]))) +;;display with +;;(send frame4 show #t) +;;add text with +;;(make-text-line "Hello World!") +;;This works for not but there are a few problems +;;first of all the window starts really small and doesn't restrict +;;resizing. Second it is always in the middle of the frame +;;Third, once text is on screen there is no way to get it off +;;But we can do better +(define frame5 (new frame% + [label "Example5"] + [width 300] + [height 300])) +(define canvas5 (new canvas% [parent frame5] + [paint-callback + (lambda (canvas dc) + (send dc set-scale 3 3) + (send dc set-text-foreground "blue") + (send dc draw-text "Don't Panic!" 0 0))])) +;;above is the example code to write some simple text, however +;;we can apply this to what we learned above to make something abit +;;more +(define frame6 (new frame% + [label "Example6"] + [width 600] + [height 700])) +(define (make-color-text string color) + (begin (new canvas% + [parent frame6] + [paint-callback + (lambda (canvas dc) + (send dc set-text-foreground color) + (send dc draw-text string 0 0 #f))]))) +;;display with +;;(send frame6 show #t) +;;write text with +;;(make-color-text "Hello World!" "purple") +;;Okay that doesn't exactly work as planned... +;;the problem with this is that each message is it's own canvas now +;;not only that but it means we can only print each line in it's +;;own color. So new plan is to make it so it adds on new strings +;;to one canvas, adding \n as nessessary. Except nevermind since +;;\n doesn't exist in this apparently + +;;Lets switch back to text and we can change it later +(define frame7 (new frame% + [label "Example7"] + [width 600] + [height 200])) +(define (make-blank-line i) + (new message% + [parent frame7] + [label " "])) +;;80 space characters +;;the i is only there to make the build-list command happy +(define Message-list (build-list 10 make-blank-line)) +;;10 make-blank-lines +;;that build-list command is super usefull for something like this +(define (move-down-list list) + (if (eq? '() (cdr list)) + '() + (begin + (move-down-list (cdr list)) + (send (car (cdr list)) set-label (send (car list) get-label))))) +(define (send-word string) + (begin + (move-down-list Message-list) + (send (car Message-list) set-label string))) +;;display with +;;(send frame7 show #t) +;;add text with +;;(send-word "Hello World") +;;Now using the send-word command I can make each word appear on the +;;screen in the place where it used to be. Starting at the top of the +;;screen and working it's way down the more text is added. +;;on the bottom line, after adding 10 lines of text, it will remove the bottom +;;most line
\ No newline at end of file diff --git a/tests/gui/windows.rkt b/tests/gui/windows.rkt new file mode 100644 index 0000000..4524673 --- /dev/null +++ b/tests/gui/windows.rkt @@ -0,0 +1,9 @@ +#lang racket + +(require racket/gui/base) + +;; Create a new window via the frame class +(define frame (new frame% [label "Example"])) + +;; Show frame(window) by calling it show method +(send frame show #t) ;; you call object methods via send diff --git a/tests/gui/windows2.rkt b/tests/gui/windows2.rkt new file mode 100644 index 0000000..3f60c80 --- /dev/null +++ b/tests/gui/windows2.rkt @@ -0,0 +1,15 @@ +#lang racket + +(require racket/gui/base) + +(define frame (new frame% + [label "Example"] + [width 300] + [height 300])) +(new canvas% [parent frame] + [paint-callback + (lambda (canvas dc) + (send dc set-scale 3 3) + (send dc set-text-foreground "blue") + (send dc draw-text "Don't Panic!" 0 0))]) +(send frame show #t) diff --git a/tests/tcpevents/README.md b/tests/tcpevents/README.md new file mode 100644 index 0000000..7c3ec21 --- /dev/null +++ b/tests/tcpevents/README.md @@ -0,0 +1 @@ +TCP communication racket concepts of events. For more see the racket guide. diff --git a/tests/tcpevents/crpovertcp.rkt b/tests/tcpevents/crpovertcp.rkt new file mode 100644 index 0000000..57874a8 --- /dev/null +++ b/tests/tcpevents/crpovertcp.rkt @@ -0,0 +1,155 @@ +#lang racket +(require math/base) ;; for random number generation + +;; globals +;; must control access via semaphore as listener thread or broadcast thread +;; might need to access it +(define connections '()) ;; maintains a list of open ports +;; ((in1, out1), (in2, out2), (in3, out3), (in4, out4) ...) + +;; lets keep thread descriptor values +; + +(define fair (make-semaphore 1)) ;; managing connections above + +(define can-i-broadcast (make-semaphore 1)) + + +;; + +;; This is a relay server making two clients communicate +;; Both `server' and `accept-and-handle' change +;; to use a custodian. +;; To start server +;; (define stop (serve 8080)) +;; (stop) to close the server + +(define (serve port-no) + (define main-cust (make-custodian)) + (parameterize ([current-custodian main-cust]) + (define listener (tcp-listen port-no 5 #t)) + (define (loop) + (accept-and-handle listener) + (loop)) + (thread loop)) + (lambda () + (displayln "\nGoodbye, shutting down all services\n") + (custodian-shutdown-all main-cust))) + +(define (accept-and-handle listener) + (define cust (make-custodian)) + (parameterize ([current-custodian cust]) + (define-values (in out) (tcp-accept listener)) + (semaphore-wait fair) + ;; keep track of open ports + (append connections (list (list in out))) + (semaphore-wait fiar) + + ; thread will communicate to all clients at once in a broadcast + ; manner + (thread (lambda () + (handle in out) ;; this handles connection with that specific client + (close-input-port in) + (close-output-port out))) + ) + ;; Watcher thread: + ;; kills current thread for waiting too long for connection from + ;; clients + (thread (lambda () + (sleep 120) + (custodian-shutdown-all cust)))) + +; (define (handle connections) +; ()) +;; each thread needs 2 new threads +(define (handle in out) + ; define function to deal with in + (define (something-to-say in) + (sync/timeout 4 (read-line-evt in 'linefeed))) + ; define function to deal with out + ; thread them each + ; (server-loop in out) + (sleep 5) ;; wait 5 seconds to guarantee client has already send message + (define echo (read-line in)) ;; bind message to echo + (displayln (string-append echo "\n")) + ; echo back the message, appending echo + ; could regex match the input to extract the name + (writeln "Admin: Hello there" out) ;; append "echo " to echo and send back + (flush-output out) +) +;; This is a single server communicating directly to the client +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;; author: Ibrahim Mkusa +;; about: print and read concurrently +;; notes: output may need to be aligned and formatted nicely +;; look into +;; https://docs.racket-lang.org/gui/text-field_.html#%28meth._%28%28%28lib._mred%2Fmain..rkt%29._text-field~25%29._get-editor%29%29 + +;; create custodian for managing all resources +;; so we can shutdown everything at once +;(define guard (make-custodian (current-custodian))) +;(current-custodian guard) +;; reads values continously from stdin and redisplays them +(define (read-loop) + (display (read-line)) + (display "\n") + (read-loop) + ) + +(define input-prompt "input: ") +(define output-prompt "output: ") + +;; prompt for username and bind to a variable username +(display "What's your name?\n") +(define username (read-line)) +(define usernamei (string-append username ": ")) ;; make username appear nicer in a prompt + +;; intelligent read, quits when user types in "quit" +(define (read-loop-i) + + + ;(semaphore-wait fair) + (display usernamei) + (define input (read-line)) + ;; do something over here with input maybe send it out + + ;; Tests input if its a quit then kills all threads + ;; An if would be better here tbh + (cond ((string=? input "quit") (begin (kill-thread a) + (kill-thread t)))) + (display (string-append output-prompt input "\n")) + ;(semaphore-post fair) + (read-loop-i) + ) + + +;; print hello world continously +;; "(hello-world)" can be executed as part of background thread +;; that prints in the event there is something in the input port +(define (hello-world) + (sleep (random-integer 0 15)) ;; sleep between 0 and 15 seconds to simulate coms + ;; with server + ;(semaphore-wait fair) + ;; we will retrieve the line printed below from the server + ;; at this time we simulate the input from different users + (define what-to-print (random-integer 0 2)) + (if (= what-to-print 0) + (display "Doug: What's up, up?\n") + (display "Fred: Looking good, good!\n")) + ;(semaphore-post fair) + (hello-world)) + +(define t (thread (lambda () + (read-loop-i)))) +(define a (thread (lambda () + (hello-world)))) + +(thread-wait t) ;; returns prompt back to drracket +;; below doesn't execute +; (sleep 10) +; (kill-thread t) +; (define a (thread (display "hello world!\n"))) +; (display "John: hello soso\n") +; (display "Emmanuel: cumbaya!!!!\n") diff --git a/tests/tcpevents/server.rkt b/tests/tcpevents/server.rkt new file mode 100644 index 0000000..4313bda --- /dev/null +++ b/tests/tcpevents/server.rkt @@ -0,0 +1,39 @@ +#lang racket + +(define (serve in-port out-port) + (let loop [] + (define evt (sync/timeout 2 + (read-line-evt in-port 'any) + (thread-receive-evt))) + (cond + [(not evt) + (displayln "Timed out, exiting") + (tcp-abandon-port in-port) + (tcp-abandon-port out-port)] + [(string? evt) + (fprintf out-port "~a~n" evt) + (flush-output out-port) + (loop)] + [else + (printf "Received a message in mailbox: ~a~n" + (thread-receive)) + (loop)]))) + +(define port-num 4321) +(define (start-server) + (define listener (tcp-listen port-num)) + (thread + (lambda () + (define-values [in-port out-port] (tcp-accept listener)) + (serve in-port out-port)))) + +(start-server) + +(define client-thread + (thread + (lambda () + (define-values [in-port out-port] (tcp-connect "localhost" port-num)) + (display "first\nsecond\nthird\n" out-port) + (flush-output out-port) + ; copy-port will block until EOF is read from in-port + (copy-port in-port (current-output-port))))) diff --git a/tests/tcpvanilla/README.md b/tests/tcpvanilla/README.md new file mode 100644 index 0000000..b8e2883 --- /dev/null +++ b/tests/tcpvanilla/README.md @@ -0,0 +1,20 @@ +a simple experiment on communication via tcp ports + +a server runs continously servicing clients. Clients connect, send a message, and +server replies with a message. Message should appear in each separate REPL area +prompt + +run server.rkt in a REPL +``` +,en server.rkt +(define stop (serve 8080)) ;; starts serve listening at port 8080 +(stop) ;; to stop server and free the ports + +``` + +run client.rkt in a separate REPL +``` +,en client.rkt +(define stop (client 8080)) ;; starts client talking to server at port 8080 + +``` diff --git a/tests/tcpvanilla/client.rkt b/tests/tcpvanilla/client.rkt new file mode 100644 index 0000000..967d2b9 --- /dev/null +++ b/tests/tcpvanilla/client.rkt @@ -0,0 +1,72 @@ +#lang racket + +;; Both `server' and `accept-and-handle' change +;; to use a custodian. +;; To start server +;; (define stop (client 8080)) +;; use your web browser to connect localhost:8080 greeted with "hello world" +;; (stop) to close the server + +(define (client port-no) + (define main-client-cust (make-custodian)) + (parameterize ([current-custodian main-client-cust]) + ;; connect to server at port 8080 + (define-values (in out) (tcp-connect "localhost" port-no)) ;; define values + ;; binds to multiple values akin to unpacking tuples in python + ; (thread (lambda () + (chat in out) + (close-input-port in) + (close-output-port out)) + (custodian-shutdown-all main-client-cust)) + + ; (sleep 60) ;; run for 3 minutes then close + ; (define (loop) + ; (write (read-line (current-input-port)) out) + ; (flush-output out) + ; (write (read-line in) (current-output-port)) + ; (define listener (tcp-listen port-no 5 #t)) + ; (define (loop) + ; (accept-and-handle listener) + ; (loop)) + ; (thread loop))) + ; (custodian-shutdown-all main-client-cust) + #| (lambda () |# + ; (displayln "Goodbye, shutting down client\n") + #| (custodian-shutdown-all main-client-cust)) |# + +(define (chat in out) + ; (driver-loop in out) + (writeln "Ibrahim: Hello, anyone in chat?" out) + (flush-output out) ;; ports are buffered in racket must flush or you + ;; will read #eof + (sleep 10) ;; wait 10 seconds + (define serv-message (read-line in)) + (displayln serv-message) ;; read the servers replay message which is original + ;; with echo appended to it + ) + +; (define input-prompt "Hermes: ") + +(define (driver-loop in out) + ; (prompt-for-input input-prompt) + (display ">>> ") + (define input (read)) + (writeln (string-append "Ibrahim: " input) out) + (flush-output out) + ; (sleep 10) + (define output (read-line in)) + (displayln output) + (driver-loop in out)) + + +#| (let ((input (read))) |# +; ) +; (let ((input (read))) +; (let ((output (mc-eval input the-global-environment))) +; (announce-output output-prompt) +; (user-print output))) +; (driver-loop)) +; +; (define (announce-output string) +; (display string)) +#| |# diff --git a/tests/tcpvanilla/client2.rkt b/tests/tcpvanilla/client2.rkt new file mode 100644 index 0000000..47e3052 --- /dev/null +++ b/tests/tcpvanilla/client2.rkt @@ -0,0 +1,43 @@ +#lang racket + +;; Both `server' and `accept-and-handle' change +;; to use a custodian. +;; To start server +;; (define stop (client 8080)) +;; use your web browser to connect localhost:8080 greeted with "hello world" +;; (stop) to close the server + +(define (client port-no) + (define main-client-cust (make-custodian)) + (parameterize ([current-custodian main-client-cust]) + ;; connect to server at port 8080 + (define-values (in out) (tcp-connect "localhost" port-no)) ;; define values + ;; binds to multiple values akin to unpacking tuples in python + (thread (lambda () + (send-message in out) + (close-input-port in) + (close-output-port out)))) + (sleep 20) + ; (define (loop) + ; (write (read-line (current-input-port)) out) + ; (flush-output out) + ; (write (read-line in) (current-output-port)) + ; (define listener (tcp-listen port-no 5 #t)) + ; (define (loop) + ; (accept-and-handle listener) + ; (loop)) + ; (thread loop))) + (custodian-shutdown-all main-client-cust) + #| (lambda () |# + ; (displayln "Goodbye, shutting down client\n") + #| (custodian-shutdown-all main-client-cust)) |#) + +(define (send-message input-port output-port) + (writeln "Doug: Hello, how's it going?" output-port) + (flush-output output-port) ;; ports are buffered in racket must flush or you + ;; will read #eof + (sleep 10) ;; wait 10 seconds + (define serv-message (read-line input-port)) + (displayln serv-message) ;; read the servers replay message which is original + ;; with echo appended to it + ) diff --git a/tests/tcpvanilla/server.rkt b/tests/tcpvanilla/server.rkt new file mode 100644 index 0000000..bf72aff --- /dev/null +++ b/tests/tcpvanilla/server.rkt @@ -0,0 +1,58 @@ +#lang racket + +;; Both `server' and `accept-and-handle' change +;; to use a custodian. +;; To start server +;; (define stop (serve 8080)) +;; use your web browser to connect localhost:8080 greeted with "hello world" +;; (stop) to close the server + +(define (serve port-no) + (define main-cust (make-custodian)) + (parameterize ([current-custodian main-cust]) + (define listener (tcp-listen port-no 5 #t)) + (define (loop) + (accept-and-handle listener) + (loop)) + (thread loop)) + (lambda () + (displayln "\nGoodbye, shutting down all services\n") + (custodian-shutdown-all main-cust))) + +(define (accept-and-handle listener) + (define cust (make-custodian)) + (parameterize ([current-custodian cust]) + (define-values (in out) (tcp-accept listener)) + (thread (lambda () + (handle in out) ;; this handles connection with that specific client + (close-input-port in) + (close-output-port out)))) + ;; Watcher thread: + (thread (lambda () + (sleep 120) + (custodian-shutdown-all cust)))) + +(define (handle in out) + ; (server-loop in out) + (sleep 5) ;; wait 5 seconds to guarantee client has already send message + (define echo (read-line in)) ;; bind message to echo + (displayln (string-append echo "\n")) + ; echo back the message, appending echo + ; could regex match the input to extract the name + (writeln "Admin: Hello there" out) ;; append "echo " to echo and send back + (flush-output out) +) + +(define input-prompt "Hermes: ") + +(define (server-loop in out) + (define echo (read-line in)) + (displayln echo) + (display ">>> ") + + (define input (read)) + (writeln (string-append "Admin: " input) out) + (flush-output out) + ; (sleep 10) + (server-loop in out)) + diff --git a/tests/tcpvanilla/tcptalk.rkt b/tests/tcpvanilla/tcptalk.rkt new file mode 100644 index 0000000..d069851 --- /dev/null +++ b/tests/tcpvanilla/tcptalk.rkt @@ -0,0 +1,30 @@ +#lang racket + +(define listener (tcp-listen 8083 5 #t)) ;; listener to service connection requests +;; client attempts to connect. Receives an input and output port +(define-values (client-in client-out) (tcp-connect "localhost" 8083)) +;; server accepts the connection request. Also gets a pair of ports +(define-values (server-in server-out) (tcp-accept listener)) + +;; client sends identifying message +(display (string-append "Client:My name is " "Ibrahim" "\n") + client-out) +(flush-output client-out) ;; must flush as ports are buffered in racket + +;; server receives and reads it +;; cooler if on separate racket instances +(read-line server-in) ;; --> "Client:My name is #hostname. +;; server replies +(display (string-append "Server:Hi " "Ibrahim" "\n") server-out) +(flush-output server-out) ;; flush flush + +;; client displays server message +(read-line client-in) +(close-output-port server-out) +(close-output-port client-out) +(read-line client-in) ;; --> eof object #eof +(read-line server-in) ;; --> eof object #eof +(tcp-close listener) +; (custodian-shutdown-all (current-custodian)) ;; release all resources including + ;; tcp, file, custom ports + ;; application exits |