main.go raw

   1  package main
   2  
   3  import "io"
   4  import "moxie"
   5  
   6  // B.0.4 stress test: sustained codec round-trip under load.
   7  // 10000 messages with mixed-size variable payloads. Exercises the
   8  // Codec serialization path repeatedly to catch GC/heap interactions
   9  // that single-shot tests miss.
  10  
  11  type Msg struct {
  12  	Seq  uint32
  13  	Sum  uint32
  14  	Body []byte
  15  }
  16  
  17  func (m Msg) EncodeTo(w io.Writer) error {
  18  	var hdr [8]byte
  19  	hdr[0] = byte(m.Seq)
  20  	hdr[1] = byte(m.Seq >> 8)
  21  	hdr[2] = byte(m.Seq >> 16)
  22  	hdr[3] = byte(m.Seq >> 24)
  23  	hdr[4] = byte(m.Sum)
  24  	hdr[5] = byte(m.Sum >> 8)
  25  	hdr[6] = byte(m.Sum >> 16)
  26  	hdr[7] = byte(m.Sum >> 24)
  27  	if _, err := w.Write(hdr[:]); err != nil {
  28  		return err
  29  	}
  30  	var sz [4]byte
  31  	l := uint32(len(m.Body))
  32  	sz[0] = byte(l)
  33  	sz[1] = byte(l >> 8)
  34  	sz[2] = byte(l >> 16)
  35  	sz[3] = byte(l >> 24)
  36  	if _, err := w.Write(sz[:]); err != nil {
  37  		return err
  38  	}
  39  	_, err := w.Write(m.Body)
  40  	return err
  41  }
  42  
  43  func (m *Msg) DecodeFrom(r io.Reader) error {
  44  	var hdr [8]byte
  45  	if _, err := io.ReadFull(r, hdr[:]); err != nil {
  46  		return err
  47  	}
  48  	m.Seq = uint32(hdr[0]) | uint32(hdr[1])<<8 | uint32(hdr[2])<<16 | uint32(hdr[3])<<24
  49  	m.Sum = uint32(hdr[4]) | uint32(hdr[5])<<8 | uint32(hdr[6])<<16 | uint32(hdr[7])<<24
  50  	var sz [4]byte
  51  	if _, err := io.ReadFull(r, sz[:]); err != nil {
  52  		return err
  53  	}
  54  	l := uint32(sz[0]) | uint32(sz[1])<<8 | uint32(sz[2])<<16 | uint32(sz[3])<<24
  55  	m.Body = make([]byte, l)
  56  	_, err := io.ReadFull(r, m.Body)
  57  	return err
  58  }
  59  
  60  func mirror(in chan Msg, out chan Msg, done chan moxie.Uint32) {
  61  	count := uint32(0)
  62  	for {
  63  		m := <-in
  64  		if m.Seq == 0xFFFFFFFF {
  65  			break
  66  		}
  67  		// Recompute sum on body to verify integrity.
  68  		s := uint32(0)
  69  		for i := 0; i < len(m.Body); i++ {
  70  			s += uint32(m.Body[i])
  71  		}
  72  		out <- Msg{Seq: m.Seq, Sum: s, Body: m.Body}
  73  		count++
  74  	}
  75  	done <- moxie.Uint32(count)
  76  }
  77  
  78  func main() {
  79  	in := make(chan Msg)
  80  	out := make(chan Msg)
  81  	done := make(chan moxie.Uint32)
  82  	spawn(mirror, in, out, done)
  83  
  84  	const N = uint32(10000)
  85  	for i := uint32(0); i < N; i++ {
  86  		// Varying body size: 0, 1, 2, ..., 1023, 0, 1, ...
  87  		bodyLen := int(i % 1024)
  88  		body := make([]byte, bodyLen)
  89  		expectedSum := uint32(0)
  90  		for j := 0; j < bodyLen; j++ {
  91  			body[j] = byte((i + uint32(j)) & 0xFF)
  92  			expectedSum += uint32(body[j])
  93  		}
  94  		in <- Msg{Seq: i, Sum: 0, Body: body}
  95  		got := <-out
  96  		if got.Seq != i || got.Sum != expectedSum {
  97  			println("FAIL:stress", "i", i, "got.Seq", got.Seq, "got.Sum", got.Sum, "want.Sum", expectedSum)
  98  			return
  99  		}
 100  		if i%1000 == 0 && i > 0 {
 101  			println("progress:", i)
 102  		}
 103  	}
 104  	in <- Msg{Seq: 0xFFFFFFFF, Sum: 0, Body: nil}
 105  	count := uint32(<-done)
 106  	if count != N {
 107  		println("FAIL:stress", "count", count, "want", N)
 108  		return
 109  	}
 110  	println("PASS:stress-codec", N, "msgs")
 111  }
 112