about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-10-22 19:05:07 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-10-22 19:05:07 -0700
commitd154c121a70e27466b43d1852ec672e2f70e1f36 (patch)
tree00bf78d1af8d46e93f5e478bfc9e7a5496557b86
parent9a81d7460fdb16f4e77712e5381d9db8781f5ae6 (diff)
downloadmu-d154c121a70e27466b43d1852ec672e2f70e1f36.tar.gz
3562
Fix CI. Revert accidentally-added files.
-rw-r--r--091socket.cc8
-rw-r--r--092socket.mu230
-rw-r--r--html/091socket.cc.html8
-rw-r--r--html/092socket.mu.html230
4 files changed, 214 insertions, 262 deletions
diff --git a/091socket.cc b/091socket.cc
index bd3f4ed6..74626853 100644
--- a/091socket.cc
+++ b/091socket.cc
@@ -218,7 +218,6 @@ case _READ_FROM_SOCKET: {
 }
 :(before "End Primitive Recipe Implementations")
 case _READ_FROM_SOCKET: {
-  cerr << "$read-from-socket\n";
   long long int x = static_cast<long long int>(ingredients.at(0).at(0));
   socket_t* socket = reinterpret_cast<socket_t*>(x);
   // 1. we'd like to simply read() from the socket
@@ -228,22 +227,19 @@ case _READ_FROM_SOCKET: {
   // 3. but poll() will block on EOF, so only use poll() on the very first
   // $read-from-socket on a socket
   if (!socket->polled) {
+    socket->polled = true;
     pollfd p;
     bzero(&p, sizeof(p));
     p.fd = socket->fd;
     p.events = POLLIN | POLLHUP;
-    if (poll(&p, /*num pollfds*/1, /*timeout*/100/*ms*/) <= 0) {
+    if (poll(&p, /*num pollfds*/1, /*no timeout*/-1) <= 0) {
       raise << maybe(current_recipe_name()) << "error in $read-from-socket\n" << end();
       products.resize(2);
       products.at(0).push_back(0);
       products.at(1).push_back(false);
       break;
     }
-    cerr << "poll output: " << p.revents << '\n';
-    cerr << "setting socket->polled\n";
-    socket->polled = true;
   }
-  cerr << "$read-from-socket " << x << " continuing\n";
   int bytes = static_cast<int>(ingredients.at(1).at(0));
   char* contents = new char[bytes];
   bzero(contents, bytes);
diff --git a/092socket.mu b/092socket.mu
index 1fd2586b..6a5c427a 100644
--- a/092socket.mu
+++ b/092socket.mu
@@ -1,87 +1,69 @@
-# Wrappers around socket primitives that are easier to test.
+# Wrappers around socket primitives that take a 'local-network' object and are
+# thus easier to test.
 #
-# To test client operations, use `assume-resources` with a filename that
-# begins with a hostname. (Filenames starting with '/' are assumed to be
-# local.)
+# The current semantics of fake port-connections don't match UNIX socket ones,
+# but we'll improve them as we learn more.
+
+container local-network [
+  data:&:@:port-connection
+]
+
+# Port connections represent connections to ports on localhost.
+# Before passing a local-network object to network functions
+# `start-reading-socket` and `start-writing-socket`, add port-connections to
+# the local-network.
+#
+# For reading, `receive-from-socket` will check for a
+# port-connection on the port parameter that's been passed in. If there's
+# no port-connection for that port, it will return nothing and log an error.
+# If there is a port-connection for that port, it will transmit the contents
+# to the provided sink.
 #
-# To test server operations, just run a real client against localhost.
+# For writing, `start-writing-socket` returns a sink connecting the
+# caller to the socket on the passed-in port.
+container port-connection [
+  port:num
+  contents:text
+]
 
-scenario example-server-test [
+def new-port-connection port:num, contents:text -> p:&:port-connection [
   local-scope
-  # test server without a fake on a random (real) port
-  # that way repeatedly running the test will give ports time to timeout and
-  # close before reusing them
-  make-random-nondeterministic
-  port:num <- random-in-range 0/real-random-numbers, 8000, 8100
-  run [
-    socket:num <- $open-server-socket port
-    $print [server socket: ], socket, 10/newline
-    assert socket, [ 
-F - example-server-test: $open-server-socket failed]
-    $print [starting up server routine], 10/newline
-    handler-routine:number <- start-running serve-one-request socket, example-handler
-  ]
-  $print [starting to read from port ], port, 10/newline
-  source:&:source:char <- start-reading-from-network 0/real-resources, [localhost], [/], port
-  response:text <- drain source
-  10:@:char/raw <- copy *response
-  memory-should-contain [
-    10:array:character <- [abc]
-  ]
+  load-ingredients
+  p:&:port-connection <- new port-connection:type
+  *p <- merge port, contents
 ]
-# helper just for this scenario
-def example-handler query:text -> response:text [
+
+def new-fake-network -> n:&:local-network [
   local-scope
   load-ingredients
-  reply [abc]
+  n:&:local-network <- new local-network:type
+  local-network-ports:&:@:port-connection <- new port-connection:type, 0
+  *n <- put *n, data:offset, local-network-ports
 ]
 
-#? scenario example-client-test [
-#?   local-scope
-#?   assume-resources [
-#?     [example.com/] -> [abc]
-#?   ]
-#?   run [
-#?     source:&:source:char <- start-reading-from-network resources, [example.com], [/]
-#?   ]
-#?   contents:text <- drain source
-#?   10:@:char/raw <- copy *contents
-#?   memory-should-contain [
-#?     10:address:character <- [abc]
-#?   ]
-#? ]
-
-type request-handler = (recipe text -> text)
-
-def serve-one-request socket:num, request-handler:request-handler [
+scenario write-to-fake-socket [
   local-scope
-  load-ingredients
-  session:num <- $accept socket
-  $print [server session socket: ], session, 10/newline
-  assert session, [ 
-F - example-server-test: $accept failed]
-  contents:&:source:char, sink:&:sink:char <- new-channel 30
-  sink <- start-running receive-from-socket session, sink
-  query:text <- drain contents
-  response:text <- call request-handler, query
-  write-to-socket session, response
-  $close-socket session
+  single-port-network:&:local-network <- new-fake-network
+  sink:&:sink:char, writer:num/routine <- start-writing-socket single-port-network, 8080
+  sink <- write sink, 120/x
+  close sink
+  wait-for-routine writer
+  tested-port-connections:&:@:port-connection <- get *single-port-network, data:offset
+  tested-port-connection:port-connection <- index *tested-port-connections, 0
+  contents:text <- get tested-port-connection, contents:offset
+  10:@:char/raw <- copy *contents
+  memory-should-contain [
+    10:array:character <- [x]
+  ]
 ]
 
 def start-reading-from-network resources:&:resources, host:text, path:text -> contents:&:source:char [
   local-scope
   load-ingredients
-  $print [running start-reading-from-network], 10/newline
-  {
-    port:num, port-found?:boolean <- next-ingredient
-    break-if port-found?
-    port <- copy 80/http-port
-  }
   {
     break-if resources
     # real network
-    socket:num <- $open-client-socket host, port
-    $print [client socket: ], socket, 10/newline
+    socket:num <- $open-client-socket host, 80/http-port
     assert socket, [contents]
     req:text <- interpolate [GET _ HTTP/1.1], path
     request-socket socket, req
@@ -120,72 +102,70 @@ def request-socket socket:num, s:text -> socket:num [
   $write-to-socket socket, 10/lf
 ]
 
-#? def start-writing-socket network:&:local-network, port:num -> sink:&:sink:char, routine-id:num [
-#?   local-scope
-#?   load-ingredients
-#?   source:&:source:char, sink:&:sink:char <- new-channel 30
-#?   {
-#?     break-if network
-#?     socket:num <- $open-server-socket port
-#?     session:num <- $accept socket
-#?     # TODO Create channel implementation of write-to-socket.
-#?     return sink, 0/routine-id
-#?   }
-#?   # fake network
-#?   routine-id <- start-running transmit-to-fake-socket network, port, source
-#? ]
+def start-writing-socket network:&:local-network, port:num -> sink:&:sink:char, routine-id:num [
+  local-scope
+  load-ingredients
+  source:&:source:char, sink:&:sink:char <- new-channel 30
+  {
+    break-if network
+    socket:num <- $open-server-socket port
+    session:num <- $accept socket
+    # TODO Create channel implementation of write-to-socket.
+    return sink, 0/routine-id
+  }
+  # fake network
+  routine-id <- start-running transmit-to-fake-socket network, port, source
+]
 
-#? def transmit-to-fake-socket network:&:local-network, port:num, source:&:source:char -> network:&:local-network, source:&:source:char [
-#?   local-scope
-#?   load-ingredients
-#?   # compute new port connection contents
-#?   buf:&:buffer <- new-buffer 30
-#?   {
-#?     c:char, done?:bool, source <- read source
-#?     break-unless c
-#?     buf <- append buf, c
-#?     break-if done?
-#?     loop
-#?   }
-#?   contents:text <- buffer-to-array buf
-#?   new-port-connection:&:port-connection <- new-port-connection port, contents
-#?   # Got the contents of the channel, time to write to fake port.
-#?   i:num <- copy 0
-#?   port-connections:&:@:port-connection <- get *network, data:offset
-#?   len:num <- length *port-connections
-#?   {
-#?     done?:bool <- greater-or-equal i, len
-#?     break-if done?
-#?     current:port-connection <- index *port-connections, i
-#?     current-port:num <- get current, port:offset
-#?     ports-match?:bool <- equal current-port, port
-#?     i <- add i, 1
-#?     loop-unless ports-match?
-#?     # Found an existing connection on this port, overwrite.
-#?     put-index *port-connections, i, *new-port-connection
-#?     reply
-#?   }
-#?   # Couldn't find an existing connection on this port, initialize a new one.
-#?   new-len:num <- add len, 1
-#?   new-port-connections:&:@:port-connection <- new port-connection:type, new-len
-#?   put *network, data:offset, new-port-connections
-#?   i:num <- copy 0
-#?   {
-#?     done?:bool <- greater-or-equal i, len
-#?     break-if done?
-#?     tmp:port-connection <- index *port-connections, i
-#?     put-index *new-port-connections, i, tmp
-#?   }
-#?   put-index *new-port-connections, len, *new-port-connection
-#? ]
+def transmit-to-fake-socket network:&:local-network, port:num, source:&:source:char -> network:&:local-network, source:&:source:char [
+  local-scope
+  load-ingredients
+  # compute new port connection contents
+  buf:&:buffer <- new-buffer 30
+  {
+    c:char, done?:bool, source <- read source
+    break-unless c
+    buf <- append buf, c
+    break-if done?
+    loop
+  }
+  contents:text <- buffer-to-array buf
+  new-port-connection:&:port-connection <- new-port-connection port, contents
+  # Got the contents of the channel, time to write to fake port.
+  i:num <- copy 0
+  port-connections:&:@:port-connection <- get *network, data:offset
+  len:num <- length *port-connections
+  {
+    done?:bool <- greater-or-equal i, len
+    break-if done?
+    current:port-connection <- index *port-connections, i
+    current-port:num <- get current, port:offset
+    ports-match?:bool <- equal current-port, port
+    i <- add i, 1
+    loop-unless ports-match?
+    # Found an existing connection on this port, overwrite.
+    put-index *port-connections, i, *new-port-connection
+    reply
+  }
+  # Couldn't find an existing connection on this port, initialize a new one.
+  new-len:num <- add len, 1
+  new-port-connections:&:@:port-connection <- new port-connection:type, new-len
+  put *network, data:offset, new-port-connections
+  i:num <- copy 0
+  {
+    done?:bool <- greater-or-equal i, len
+    break-if done?
+    tmp:port-connection <- index *port-connections, i
+    put-index *new-port-connections, i, tmp
+  }
+  put-index *new-port-connections, len, *new-port-connection
+]
 
 def receive-from-socket socket:num, sink:&:sink:char -> sink:&:sink:char [
   local-scope
   load-ingredients
   {
-    $print [read-from-socket ], socket, 10/newline
     req:text, eof?:bool <- $read-from-socket socket, 4096/bytes
-    loop-unless req
     bytes-read:num <- length *req
     i:num <- copy 0
     {
diff --git a/html/091socket.cc.html b/html/091socket.cc.html
index a3bd7316..a81f4c79 100644
--- a/html/091socket.cc.html
+++ b/html/091socket.cc.html
@@ -251,7 +251,6 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span
 <span class="Delimiter">}</span>
 <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
 <span class="Normal">case</span> _READ_FROM_SOCKET: <span class="Delimiter">{</span>
-  cerr &lt;&lt; <span class="Constant">&quot;$read-from-socket</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
   <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
   socket_t* socket = <span class="Normal">reinterpret_cast</span>&lt;socket_t*&gt;<span class="Delimiter">(</span>x<span class="Delimiter">);</span>
   <span class="Comment">// 1. we'd like to simply read() from the socket</span>
@@ -261,22 +260,19 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span
   <span class="Comment">// 3. but poll() will block on EOF, so only use poll() on the very first</span>
   <span class="Comment">// $read-from-socket on a socket</span>
   <span class="Normal">if</span> <span class="Delimiter">(</span>!socket<span class="Delimiter">-&gt;</span>polled<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    socket<span class="Delimiter">-&gt;</span>polled = <span class="Constant">true</span><span class="Delimiter">;</span>
     pollfd p<span class="Delimiter">;</span>
     bzero<span class="Delimiter">(</span>&amp;p<span class="Delimiter">,</span> <span class="Normal">sizeof</span><span class="Delimiter">(</span>p<span class="Delimiter">));</span>
     p<span class="Delimiter">.</span>fd = socket<span class="Delimiter">-&gt;</span>fd<span class="Delimiter">;</span>
     p<span class="Delimiter">.</span>events = POLLIN | POLLHUP<span class="Delimiter">;</span>
-    <span class="Normal">if</span> <span class="Delimiter">(</span>poll<span class="Delimiter">(</span>&amp;p<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">num pollfds</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">timeout</span><span class="Comment">*/</span><span class="Constant">100</span><span class="Comment">/*</span><span class="Comment">ms</span><span class="Comment">*/</span><span class="Delimiter">)</span> &lt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    <span class="Normal">if</span> <span class="Delimiter">(</span>poll<span class="Delimiter">(</span>&amp;p<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">num pollfds</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">no timeout</span><span class="Comment">*/</span>-<span class="Constant">1</span><span class="Delimiter">)</span> &lt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
       raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;error in $read-from-socket</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span>
       products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span>
       products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
       products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">);</span>
       <span class="Identifier">break</span><span class="Delimiter">;</span>
     <span class="Delimiter">}</span>
-    cerr &lt;&lt; <span class="Constant">&quot;poll output: &quot;</span> &lt;&lt; p<span class="Delimiter">.</span>revents &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-    cerr &lt;&lt; <span class="Constant">&quot;setting socket-&gt;polled</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
-    socket<span class="Delimiter">-&gt;</span>polled = <span class="Constant">true</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
-  cerr &lt;&lt; <span class="Constant">&quot;$read-from-socket &quot;</span> &lt;&lt; x &lt;&lt; <span class="Constant">&quot; continuing</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
   <span class="Normal">int</span> bytes = <span class="Normal">static_cast</span>&lt;<span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
   <span class="Normal">char</span>* contents = <span class="Normal">new</span> <span class="Normal">char</span>[bytes]<span class="Delimiter">;</span>
   bzero<span class="Delimiter">(</span>contents<span class="Delimiter">,</span> bytes<span class="Delimiter">);</span>
diff --git a/html/092socket.mu.html b/html/092socket.mu.html
index 72ffa17c..186c7c3b 100644
--- a/html/092socket.mu.html
+++ b/html/092socket.mu.html
@@ -33,90 +33,72 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
 </head>
 <body>
 <pre id='vimCodeElement'>
-<span class="Comment"># Wrappers around socket primitives that are easier to test.</span>
+<span class="Comment"># Wrappers around socket primitives that take a 'local-network' object and are</span>
+<span class="Comment"># thus easier to test.</span>
 <span class="Comment">#</span>
-<span class="Comment"># To test client operations, use `assume-resources` with a filename that</span>
-<span class="Comment"># begins with a hostname. (Filenames starting with '/' are assumed to be</span>
-<span class="Comment"># local.)</span>
+<span class="Comment"># The current semantics of fake port-connections don't match UNIX socket ones,</span>
+<span class="Comment"># but we'll improve them as we learn more.</span>
+
+<span class="muData">container</span> local-network [
+  data:&amp;:@:port-connection
+]
+
+<span class="Comment"># Port connections represent connections to ports on localhost.</span>
+<span class="Comment"># Before passing a local-network object to network functions</span>
+<span class="Comment"># `start-reading-socket` and `start-writing-socket`, add port-connections to</span>
+<span class="Comment"># the local-network.</span>
+<span class="Comment">#</span>
+<span class="Comment"># For reading, `receive-from-socket` will check for a</span>
+<span class="Comment"># port-connection on the port parameter that's been passed in. If there's</span>
+<span class="Comment"># no port-connection for that port, it will return nothing and log an error.</span>
+<span class="Comment"># If there is a port-connection for that port, it will transmit the contents</span>
+<span class="Comment"># to the provided sink.</span>
 <span class="Comment">#</span>
-<span class="Comment"># To test server operations, just run a real client against localhost.</span>
+<span class="Comment"># For writing, `start-writing-socket` returns a sink connecting the</span>
+<span class="Comment"># caller to the socket on the passed-in port.</span>
+<span class="muData">container</span> port-connection [
+  port:num
+  contents:text
+]
 
-<span class="muScenario">scenario</span> example-server-test [
+<span class="muRecipe">def</span> new-port-connection port:num, contents:text<span class="muRecipe"> -&gt; </span>p:&amp;:port-connection [
   <span class="Constant">local-scope</span>
-  <span class="Comment"># test server without a fake on a random (real) port</span>
-  <span class="Comment"># that way repeatedly running the test will give ports time to timeout and</span>
-  <span class="Comment"># close before reusing them</span>
-  make-random-nondeterministic
-  port:num<span class="Special"> &lt;- </span>random-in-range <span class="Constant">0/real-random-numbers</span>, <span class="Constant">8000</span>, <span class="Constant">8100</span>
-  run [
-    socket:num<span class="Special"> &lt;- </span>$open-server-socket port
-    $print <span class="Constant">[server socket: ]</span>, socket, <span class="Constant">10/newline</span>
-    assert socket, <span class="Constant">[ </span>
-<span class="Constant">F - example-server-test: $open-server-socket failed]</span>
-    $print <span class="Constant">[starting up server routine]</span>, <span class="Constant">10/newline</span>
-    handler-routine:number<span class="Special"> &lt;- </span>start-running serve-one-request socket, example-handler
-  ]
-  $print <span class="Constant">[starting to read from port ]</span>, port, <span class="Constant">10/newline</span>
-  source:&amp;:source:char<span class="Special"> &lt;- </span>start-reading-from-network <span class="Constant">0/real-resources</span>, <span class="Constant">[localhost]</span>, <span class="Constant">[/]</span>, port
-  response:text<span class="Special"> &lt;- </span>drain source
-  <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *response
-  memory-should-contain [
-    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[abc]</span>
-  ]
+  <span class="Constant">load-ingredients</span>
+  p:&amp;:port-connection<span class="Special"> &lt;- </span>new <span class="Constant">port-connection:type</span>
+  *p<span class="Special"> &lt;- </span>merge port, contents
 ]
-<span class="Comment"># helper just for this scenario</span>
-<span class="muRecipe">def</span> example-handler query:text<span class="muRecipe"> -&gt; </span>response:text [
+
+<span class="muRecipe">def</span> new-fake-network<span class="muRecipe"> -&gt; </span>n:&amp;:local-network [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
-  <span class="muControl">reply</span> <span class="Constant">[abc]</span>
+  n:&amp;:local-network<span class="Special"> &lt;- </span>new <span class="Constant">local-network:type</span>
+  local-network-ports:&amp;:@:port-connection<span class="Special"> &lt;- </span>new <span class="Constant">port-connection:type</span>, <span class="Constant">0</span>
+  *n<span class="Special"> &lt;- </span>put *n, <span class="Constant">data:offset</span>, local-network-ports
 ]
 
-<span class="CommentedCode">#? scenario example-client-test [</span>
-<span class="CommentedCode">#?   local-scope</span>
-<span class="CommentedCode">#?   assume-resources [</span>
-<span class="CommentedCode">#?     [example.com/] -&gt; [abc]</span>
-<span class="CommentedCode">#?   ]</span>
-<span class="CommentedCode">#?   run [</span>
-<span class="CommentedCode">#?     source:&amp;:source:char &lt;- start-reading-from-network resources, [example.com], [/]</span>
-<span class="CommentedCode">#?   ]</span>
-<span class="CommentedCode">#?   contents:text &lt;- drain source</span>
-<span class="CommentedCode">#?   10:@:char/raw &lt;- copy *contents</span>
-<span class="CommentedCode">#?   memory-should-contain [</span>
-<span class="CommentedCode">#?     10:address:character &lt;- [abc]</span>
-<span class="CommentedCode">#?   ]</span>
-<span class="CommentedCode">#? ]</span>
-
-<span class="muData">type</span> request-handler = (recipe text<span class="muRecipe"> -&gt; </span>text)
-
-<span class="muRecipe">def</span> serve-one-request socket:num, request-handler:request-handler [
+<span class="muScenario">scenario</span> write-to-fake-socket [
   <span class="Constant">local-scope</span>
-  <span class="Constant">load-ingredients</span>
-  session:num<span class="Special"> &lt;- </span>$accept socket
-  $print <span class="Constant">[server session socket: ]</span>, session, <span class="Constant">10/newline</span>
-  assert session, <span class="Constant">[ </span>
-<span class="Constant">F - example-server-test: $accept failed]</span>
-  contents:&amp;:source:char, sink:&amp;:sink:char<span class="Special"> &lt;- </span>new-channel <span class="Constant">30</span>
-  sink<span class="Special"> &lt;- </span>start-running receive-from-socket session, sink
-  query:text<span class="Special"> &lt;- </span>drain contents
-  response:text<span class="Special"> &lt;- </span>call request-handler, query
-  write-to-socket session, response
-  $close-socket session
+  single-port-network:&amp;:local-network<span class="Special"> &lt;- </span>new-fake-network
+  sink:&amp;:sink:char, writer:num/routine<span class="Special"> &lt;- </span>start-writing-socket single-port-network, <span class="Constant">8080</span>
+  sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">120/x</span>
+  close sink
+  wait-for-routine writer
+  tested-port-connections:&amp;:@:port-connection<span class="Special"> &lt;- </span>get *single-port-network, <span class="Constant">data:offset</span>
+  tested-port-connection:port-connection<span class="Special"> &lt;- </span>index *tested-port-connections, <span class="Constant">0</span>
+  contents:text<span class="Special"> &lt;- </span>get tested-port-connection, <span class="Constant">contents:offset</span>
+  <span class="Constant">10</span>:@:char/<span class="Special">raw &lt;- </span>copy *contents
+  memory-should-contain [
+    <span class="Constant">10</span>:array:character<span class="Special"> &lt;- </span><span class="Constant">[x]</span>
+  ]
 ]
 
 <span class="muRecipe">def</span> start-reading-from-network resources:&amp;:resources, host:text, path:text<span class="muRecipe"> -&gt; </span>contents:&amp;:source:char [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
-  $print <span class="Constant">[running start-reading-from-network]</span>, <span class="Constant">10/newline</span>
-  <span class="Delimiter">{</span>
-    port:num, port-found?:boolean<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-    <span class="muControl">break-if</span> port-found?
-    port<span class="Special"> &lt;- </span>copy <span class="Constant">80/http-port</span>
-  <span class="Delimiter">}</span>
   <span class="Delimiter">{</span>
     <span class="muControl">break-if</span> resources
     <span class="Comment"># real network</span>
-    socket:num<span class="Special"> &lt;- </span>$open-client-socket host, port
-    $print <span class="Constant">[client socket: ]</span>, socket, <span class="Constant">10/newline</span>
+    socket:num<span class="Special"> &lt;- </span>$open-client-socket host, <span class="Constant">80/http-port</span>
     assert socket, <span class="Constant">[contents]</span>
     req:text<span class="Special"> &lt;- </span>interpolate <span class="Constant">[GET _ HTTP/1.1]</span>, path
     request-socket socket, req
@@ -155,72 +137,70 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color
   $write-to-socket socket, <span class="Constant">10/lf</span>
 ]
 
-<span class="CommentedCode">#? def start-writing-socket network:&amp;:local-network, port:num -&gt; sink:&amp;:sink:char, routine-id:num [</span>
-<span class="CommentedCode">#?   local-scope</span>
-<span class="CommentedCode">#?   load-ingredients</span>
-<span class="CommentedCode">#?   source:&amp;:source:char, sink:&amp;:sink:char &lt;- new-channel 30</span>
-<span class="CommentedCode">#?   {</span>
-<span class="CommentedCode">#?     break-if network</span>
-<span class="CommentedCode">#?     socket:num &lt;- $open-server-socket port</span>
-<span class="CommentedCode">#?     session:num &lt;- $accept socket</span>
-<span class="CommentedCode">#?     # TODO Create channel implementation of write-to-socket.</span>
-<span class="CommentedCode">#?     return sink, 0/routine-id</span>
-<span class="CommentedCode">#?   }</span>
-<span class="CommentedCode">#?   # fake network</span>
-<span class="CommentedCode">#?   routine-id &lt;- start-running transmit-to-fake-socket network, port, source</span>
-<span class="CommentedCode">#? ]</span>
+<span class="muRecipe">def</span> start-writing-socket network:&amp;:local-network, port:num<span class="muRecipe"> -&gt; </span>sink:&amp;:sink:char, routine-id:num [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">load-ingredients</span>
+  source:&amp;:source:char, sink:&amp;:sink:char<span class="Special"> &lt;- </span>new-channel <span class="Constant">30</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-if</span> network
+    socket:num<span class="Special"> &lt;- </span>$open-server-socket port
+    session:num<span class="Special"> &lt;- </span>$accept socket
+    <span class="Comment"># TODO Create channel implementation of write-to-socket.</span>
+    <span class="muControl">return</span> sink, <span class="Constant">0/routine-id</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># fake network</span>
+  routine-id<span class="Special"> &lt;- </span>start-running transmit-to-fake-socket network, port, source
+]
 
-<span class="CommentedCode">#? def transmit-to-fake-socket network:&amp;:local-network, port:num, source:&amp;:source:char -&gt; network:&amp;:local-network, source:&amp;:source:char [</span>
-<span class="CommentedCode">#?   local-scope</span>
-<span class="CommentedCode">#?   load-ingredients</span>
-<span class="CommentedCode">#?   # compute new port connection contents</span>
-<span class="CommentedCode">#?   buf:&amp;:buffer &lt;- new-buffer 30</span>
-<span class="CommentedCode">#?   {</span>
-<span class="CommentedCode">#?     c:char, done?:bool, source &lt;- read source</span>
-<span class="CommentedCode">#?     break-unless c</span>
-<span class="CommentedCode">#?     buf &lt;- append buf, c</span>
-<span class="CommentedCode">#?     break-if done?</span>
-<span class="CommentedCode">#?     loop</span>
-<span class="CommentedCode">#?   }</span>
-<span class="CommentedCode">#?   contents:text &lt;- buffer-to-array buf</span>
-<span class="CommentedCode">#?   new-port-connection:&amp;:port-connection &lt;- new-port-connection port, contents</span>
-<span class="CommentedCode">#?   # Got the contents of the channel, time to write to fake port.</span>
-<span class="CommentedCode">#?   i:num &lt;- copy 0</span>
-<span class="CommentedCode">#?   port-connections:&amp;:@:port-connection &lt;- get *network, data:offset</span>
-<span class="CommentedCode">#?   len:num &lt;- length *port-connections</span>
-<span class="CommentedCode">#?   {</span>
-<span class="CommentedCode">#?     done?:bool &lt;- greater-or-equal i, len</span>
-<span class="CommentedCode">#?     break-if done?</span>
-<span class="CommentedCode">#?     current:port-connection &lt;- index *port-connections, i</span>
-<span class="CommentedCode">#?     current-port:num &lt;- get current, port:offset</span>
-<span class="CommentedCode">#?     ports-match?:bool &lt;- equal current-port, port</span>
-<span class="CommentedCode">#?     i &lt;- add i, 1</span>
-<span class="CommentedCode">#?     loop-unless ports-match?</span>
-<span class="CommentedCode">#?     # Found an existing connection on this port, overwrite.</span>
-<span class="CommentedCode">#?     put-index *port-connections, i, *new-port-connection</span>
-<span class="CommentedCode">#?     reply</span>
-<span class="CommentedCode">#?   }</span>
-<span class="CommentedCode">#?   # Couldn't find an existing connection on this port, initialize a new one.</span>
-<span class="CommentedCode">#?   new-len:num &lt;- add len, 1</span>
-<span class="CommentedCode">#?   new-port-connections:&amp;:@:port-connection &lt;- new port-connection:type, new-len</span>
-<span class="CommentedCode">#?   put *network, data:offset, new-port-connections</span>
-<span class="CommentedCode">#?   i:num &lt;- copy 0</span>
-<span class="CommentedCode">#?   {</span>
-<span class="CommentedCode">#?     done?:bool &lt;- greater-or-equal i, len</span>
-<span class="CommentedCode">#?     break-if done?</span>
-<span class="CommentedCode">#?     tmp:port-connection &lt;- index *port-connections, i</span>
-<span class="CommentedCode">#?     put-index *new-port-connections, i, tmp</span>
-<span class="CommentedCode">#?   }</span>
-<span class="CommentedCode">#?   put-index *new-port-connections, len, *new-port-connection</span>
-<span class="CommentedCode">#? ]</span>
+<span class="muRecipe">def</span> transmit-to-fake-socket network:&amp;:local-network, port:num, source:&amp;:source:char<span class="muRecipe"> -&gt; </span>network:&amp;:local-network, source:&amp;:source:char [
+  <span class="Constant">local-scope</span>
+  <span class="Constant">load-ingredients</span>
+  <span class="Comment"># compute new port connection contents</span>
+  buf:&amp;:buffer<span class="Special"> &lt;- </span>new-buffer <span class="Constant">30</span>
+  <span class="Delimiter">{</span>
+    c:char, done?:bool, source<span class="Special"> &lt;- </span>read source
+    <span class="muControl">break-unless</span> c
+    buf<span class="Special"> &lt;- </span>append buf, c
+    <span class="muControl">break-if</span> done?
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  contents:text<span class="Special"> &lt;- </span>buffer-to-array buf
+  new-port-connection:&amp;:port-connection<span class="Special"> &lt;- </span>new-port-connection port, contents
+  <span class="Comment"># Got the contents of the channel, time to write to fake port.</span>
+  i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  port-connections:&amp;:@:port-connection<span class="Special"> &lt;- </span>get *network, <span class="Constant">data:offset</span>
+  len:num<span class="Special"> &lt;- </span>length *port-connections
+  <span class="Delimiter">{</span>
+    done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, len
+    <span class="muControl">break-if</span> done?
+    current:port-connection<span class="Special"> &lt;- </span>index *port-connections, i
+    current-port:num<span class="Special"> &lt;- </span>get current, <span class="Constant">port:offset</span>
+    ports-match?:bool<span class="Special"> &lt;- </span>equal current-port, port
+    i<span class="Special"> &lt;- </span>add i, <span class="Constant">1</span>
+    <span class="muControl">loop-unless</span> ports-match?
+    <span class="Comment"># Found an existing connection on this port, overwrite.</span>
+    put-index *port-connections, i, *new-port-connection
+    <span class="muControl">reply</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># Couldn't find an existing connection on this port, initialize a new one.</span>
+  new-len:num<span class="Special"> &lt;- </span>add len, <span class="Constant">1</span>
+  new-port-connections:&amp;:@:port-connection<span class="Special"> &lt;- </span>new <span class="Constant">port-connection:type</span>, new-len
+  put *network, <span class="Constant">data:offset</span>, new-port-connections
+  i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
+  <span class="Delimiter">{</span>
+    done?:bool<span class="Special"> &lt;- </span>greater-or-equal i, len
+    <span class="muControl">break-if</span> done?
+    tmp:port-connection<span class="Special"> &lt;- </span>index *port-connections, i
+    put-index *new-port-connections, i, tmp
+  <span class="Delimiter">}</span>
+  put-index *new-port-connections, len, *new-port-connection
+]
 
 <span class="muRecipe">def</span> receive-from-socket socket:num, sink:&amp;:sink:char<span class="muRecipe"> -&gt; </span>sink:&amp;:sink:char [
   <span class="Constant">local-scope</span>
   <span class="Constant">load-ingredients</span>
   <span class="Delimiter">{</span>
-    $print <span class="Constant">[read-from-socket ]</span>, socket, <span class="Constant">10/newline</span>
     req:text, eof?:bool<span class="Special"> &lt;- </span>$read-from-socket socket, <span class="Constant">4096/bytes</span>
-    <span class="muControl">loop-unless</span> req
     bytes-read:num<span class="Special"> &lt;- </span>length *req
     i:num<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
     <span class="Delimiter">{</span>