needs tests/harness com/tcb testbegin \ OUTPUT SIDE create out TCBOut typesz allot0 54 out tcbout$ \test tcbout with empty buffer MAXWINDOWSZ out tcbout 0 #eq out TCB.buf 0 #eq \ A noop tcbout doesn't mobilize a buffer \test tcbout with some contents usedbufs markcnt const origcnt "hello" c@+ out tcbwrite 5 #eq out TCB.last 59 #eq out TCBOut.tosend 54 #eq out TCB.orig 54 #eq out TCB.bufseq 54 #eq "hello" MAXWINDOWSZ out tcbout dup 5 #eq rot 54 #eq #s[]= out TCB.last 59 #eq out TCBOut.tosend 59 #eq out TCB.orig 54 #eq \test tcback 59 out tcback out TCB.buf 0 #eq \ all sent and acknowledged? we can free the buffer out TCB.last 59 #eq out TCBOut.tosend 59 #eq out TCB.orig 59 #eq usedbufs markcnt origcnt #eq \test tcbout observes winsz and maxn 4 out winsz! "abcde" c@+ out tcbwrite 5 #eq out TCB.last 64 #eq out TCBOut.tosend 59 #eq out TCB.orig 59 #eq out TCB.bufseq 59 #eq "ab" 2 out tcbout dup 2 #eq rot 59 #eq #s[]= \ stop at maxn! "cd" 3 out tcbout dup 2 #eq rot 61 #eq #s[]= \ stop at winsz! 1 out tcbout 0 #eq \ nothing is read until we ack out TCB.last 64 #eq out TCBOut.tosend 63 #eq out TCB.orig 59 #eq out TCB.bufseq 59 #eq 63 out tcback "e" 3 out tcbout dup 1 #eq rot 63 #eq #s[]= \ and now we get the end of it out TCB.last 64 #eq out TCBOut.tosend 64 #eq out TCB.orig 63 #eq 64 out tcback out TCB.buf 0 #eq MAXWINDOWSZ out winsz! \test tcbout rollover create filler MAXWINDOWSZ allot \ first, let's advance in the buffer a bit "abcd" c@+ out tcbwrite 4 #eq 4 out tcbout 4 #eq 2drop \ sent out but not ACK, buffer still held 66 out tcback \ *partial* ACK, buffer still held out TCB.buf #true out TCB.last 68 #eq out TCBOut.tosend 68 #eq out TCB.orig 66 #eq out TCB.bufseq 64 #eq filler MAXWINDOWSZ 6 - out tcbwrite MAXWINDOWSZ 6 - #eq \ 2b before end of buf \ And now, let's write 4b to the TCB, which will put the first 2b at the end \ of the buffer and the other 2b at the beginning of it. \ But first, let's ensure that we don't write past the buffer... by writing past \ the buffer ourselves! This test will corrupt memory only if we happen to use \ the last buffer in our test TCB, which is very unlikely to happen. n"MARK" out TCB.buf MAXWINDOWSZ + ! "efgh" c@+ out tcbwrite 4 #eq out TCB.last out TCB.orig MAXWINDOWSZ + #eq \ stretched to the limit! out TCB.buf MAXWINDOWSZ + @ n"MARK" #eq \ going past the filler MAXWINDOWSZ 6 - out tcbout MAXWINDOWSZ 6 - #eq drop 68 #eq \ This write below will use the static concatenation buffer "efgh" MAXWINDOWSZ out tcbout dup 4 #eq rot 68 MAXWINDOWSZ + 6 - #eq #s[]= \test rewind \ In the test above, only the first two bytes sent were acknowledged. If it \ just so happens that no ACK is sent and that we timeout, we'll rewind there. out tcbrewind "cd" 2 out tcbout dup 2 #eq rot 66 #eq #s[]= \ INPUT SIDE 0 out tcbout$ \ free buf from tests above, we're done with it create in TCBIn typesz allot0 42 in tcbin$ \test tcbread with empty MAXWINDOWSZ in tcbread 0 #eq \test receive some in-order contents "hello" c@+ 42 in tcbin "goodbye" c@+ 47 in tcbin in TCB.buf #true in TCB.last 54 #eq in TCBIn.first 42 #eq in TCB.orig 42 #eq in TCB.bufseq 42 #eq "hellogoodbye" MAXWINDOWSZ in tcbread dup 12 #eq rot 54 #eq #s[]= in TCB.buf 0 #eq \test receive overlapping contents \ also, test that tcbread applies bounds to input "n" 42 in tcbin$ "hello" c@+ 42 in tcbin "scape" c@+ 46 in tcbin "hellscape" -1 in tcbread dup 9 #eq rot 51 #eq #s[]= in TCB.buf 0 #eq \test out-of-order contents 42 in tcbin$ "goodbye" c@+ 47 in tcbin MAXWINDOWSZ in tcbread 0 #eq "hello" c@+ 42 in tcbin in TCB.buf #true in TCB.last 54 #eq in TCBIn.first 42 #eq in TCB.orig 42 #eq in TCB.bufseq 42 #eq "hellogoodbye" MAXWINDOWSZ in tcbread dup 12 #eq rot 54 #eq #s[]= in TCB.buf 0 #eq \test can't create a hole unless last = orig \ that is, we can't create a hole in a TCB that hasn't been consumed locally. 42 in tcbin$ "hello" c@+ 42 in tcbin \ ready to be consumed, but we don't do it "foo" c@+ 60 in tcbin in TCB.last 47 #eq \test can't have more than one hole ( right ) 42 in tcbin$ "goodbye" c@+ 47 in tcbin "foo" c@+ 60 in tcbin in TCB.last 54 #eq \test can't have more than one hole ( left ) "foo" c@+ 43 in tcbin \ not touching either orig nor first in TCBIn.first 47 #eq in TCB.orig 42 #eq \test can shrink hole from left "foo" c@+ 44 in tcbin \ touching first in TCBIn.first 44 #eq in TCB.orig 42 #eq MAXWINDOWSZ in tcbread 0 #eq \ still can't consume \test can shrink hole from right "bar" c@+ 54 in tcbin \ touching last in TCB.last 57 #eq \test closing everything up! "XX" c@+ 42 in tcbin in TCBIn.first 42 #eq "XXfoogoodbyebar" MAXWINDOWSZ in tcbread dup 15 #eq rot 57 #eq #s[]= in TCB.buf 0 #eq testend