func TestCapnpWillCompileOurOutput(t *testing.T) { cv.Convey("Given a parsable golang source file with a simple struct", t, func() { cv.Convey("then when we generate capnp code, it should compile", func() { in1 := ` type in1 struct { Str string N int D float64 }` s1, err := ExtractFromString(in1) if err != nil { panic(err) } //expect1 := `struct In1 { str @0: Text; n @1: Int64; d @2: Float64; } ` //cv.So(string(s1), cv.ShouldEqual, expect1) // no news on compile is good news _, err, x := CapnpCompileFragment(s1) cv.So(err, cv.ShouldEqual, nil) x.Cleanup() }) }) }
func TestReplicaJob(t *testing.T) { cv.Convey("If we start a job with a replication factor of 2", t, func() { cv.Convey("then the first job to finish should notify and cancel the other workers on that job", func() { }) }) }
func TestEnvCannotContainKey(t *testing.T) { cv.Convey("To avoid transmitting the clusterid, the Env sent to the shepard/worker cannot contain COG_ variables or the clusterid", t, func() { cv.Convey("The 8 GOQ env var should all be subtracted by GetNonGOQEnv(), as well as any variable that has the specified cid in it", func() { // *** universal test cfg setup skipbye := false cfg := NewTestConfig() defer cfg.ByeTestConfig(&skipbye) // *** end universal test setup e := make(map[string]string) cfg.InjectConfigIntoMap(&e) e["UNTOUCHED"] = "sane" randomCid := RandomClusterId() e["SHALLNOTPASS"] = randomCid env2 := MapToEnv(e) cv.So(len(env2), cv.ShouldEqual, 11) // the 8 from cfg + UNTOUCHED and SHALLNOTPASS res := GetNonGOQEnv(env2, randomCid) cv.So(len(res), cv.ShouldEqual, 1) cv.So(res[0], cv.ShouldEqual, "UNTOUCHED=sane") }) }) }
func TestSubmitShutdownToLocalJobServ(t *testing.T) { cv.Convey("with a local jobserv, we should be able to submit a shutdown job to the server", t, func() { cv.Convey("and then server go routine should shut itself down cleanly", func() { // *** universal test cfg setup skipbye := false cfg := NewTestConfig() defer cfg.ByeTestConfig(&skipbye) // *** end universal test setup cfg.JservIP = "" jobserv, err := NewJobServ(cfg) if err != nil { panic(err) } defer CleanupOutdir(cfg) sub, err := NewLocalSubmitter(jobserv) if err != nil { panic(err) } sub.SubmitShutdownJob() <-jobserv.Done // we should get past the receive on Done when jobserv closes down: cv.So(true, cv.ShouldEqual, true) }) }) }
func TestTextAndTextListContaintingStruct(t *testing.T) { zjobBytes := CapnpEncode(`(cmd = "abc", args = ["xyz"])`, "Zjob") cv.Convey("Given a simple struct message Zjob containing a string (cmd='abc') and a list of string (args=['xyz'])", t, func() { cv.Convey("then the go-capnproto serialization should match the capnp c++ serialization", func() { seg := capn.NewBuffer(nil) zjob := air.NewRootZjob(seg) zjob.SetCmd("abc") tl := seg.NewTextList(1) tl.Set(0, "xyz") zjob.SetArgs(tl) buf := bytes.Buffer{} seg.WriteTo(&buf) act := buf.Bytes() fmt.Printf(" actual:\n") ShowBytes(act, 10) fmt.Printf("expected:\n") ShowBytes(zjobBytes, 10) cv.So(act, cv.ShouldResemble, zjobBytes) }) }) }
func Test004SingleSlice(t *testing.T) { cv.Convey("Given a parsable golang source file with type Vector struct { M []int }", t, func() { cv.Convey("then we should generate translation utility methods for List(Int64) <-> []int in the capnp output", func() { ex0 := ` type Vector struct { M []int }` cv.So(ExtractString2String(ex0), ShouldContainModuloWhiteSpace, ` func Int64ListToSliceInt(p capn.Int64List) []int { v := make([]int, p.Len()) for i := range v { v[i] = int(p.At(i)) } return v } `) cv.So(ExtractString2String(ex0), ShouldContainModuloWhiteSpace, ` func SliceIntToInt64List(seg *capn.Segment, m []int) capn.Int64List { lst := seg.NewInt64List(len(m)) for i := range m { lst.Set(i, int64(m[i])) } return lst } `) }) }) }
func TestBitList(t *testing.T) { seg, _ := zboolvec_value_FilledSegment(5, 3) text := CapnpDecodeSegment(seg, "", "aircraftlib/aircraft.capnp", "Z") expectedText := `(boolvec = [true, false, true])` cv.Convey("Given a go-capnproto created List(Bool) Z::boolvec with bool values [true, false, true]", t, func() { cv.Convey("When we decode it with capnp", func() { cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() { cv.So(text, cv.ShouldEqual, expectedText) }) cv.Convey("And our data should contain Z_BOOLVEC with contents true, false, true", func() { z := air.ReadRootZ(seg) cv.So(z.Which(), cv.ShouldEqual, air.Z_BOOLVEC) var bitlist = z.Boolvec() cv.So(bitlist.Len(), cv.ShouldEqual, 3) cv.So(bitlist.At(0), cv.ShouldEqual, true) cv.So(bitlist.At(1), cv.ShouldEqual, false) cv.So(bitlist.At(2), cv.ShouldEqual, true) }) }) }) }
func Test017WriteRead_StructPointerWithinStruct(t *testing.T) { tdir := NewTempDir() // comment the defer out to debug any rw test failures. defer tdir.Cleanup() err := exec.Command("cp", "rw3.go.txt", tdir.DirPath+"/rw3.go").Run() if err != nil { panic(err) } MainArgs([]string{os.Args[0], "-o", tdir.DirPath, "rw3.go.txt"}) cv.Convey("Given bambam generated go bindings: with a struct pointer within a struct", t, func() { cv.Convey("then we should be able to write to disk, and read back the same structure", func() { cv.So(err, cv.ShouldEqual, nil) tdir.MoveTo() err = exec.Command("capnpc", "-ogo", "schema.capnp").Run() cv.So(err, cv.ShouldEqual, nil) err = exec.Command("go", "build").Run() cv.So(err, cv.ShouldEqual, nil) // run it err = exec.Command("./" + tdir.DirPath).Run() cv.So(err, cv.ShouldEqual, nil) }) }) }
func TestDecodeOnKnownWellPackedData(t *testing.T) { // length 17 byteSliceIn := []byte{0x10, 0x5, 0x50, 0x2, 0x1, 0x1, 0x25, 0x0, 0x0, 0x11, 0x1, 0xc, 0xf, 0xd4, 0x7, 0xc, 0x7} fmt.Printf("len of byteSliceIn is %d\n", len(byteSliceIn)) // annotated: byteSliceIn := []byte{tag:0x10, 0x5, tag:0x50, 0x2, 0x1, tag:0x1, 0x25, tag:0x0, 0x0, tag:0x11, 0x1, 0xc, tag:0xf, 0xd4, 0x7, 0xc, 0x7} // length 48 expectedOut := []byte{0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1, 0x0, 0x25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xd4, 0x7, 0xc, 0x7, 0x0, 0x0, 0x0, 0x0} r := bytes.NewReader(byteSliceIn) actual, err := ioutil.ReadAll(capn.NewDecompressor(r)) if err != nil { panic(err) } cv.Convey("Given a known-to-be-correctly packed 17-byte long sequence for a ZdateVector holding a single Zdate", t, func() { cv.Convey("When we use go-capnproto NewDecompressor", func() { cv.Convey("Then we should get the same unpacked bytes as capnp provides", func() { cv.So(len(actual), cv.ShouldResemble, len(expectedOut)) cv.So(actual, cv.ShouldResemble, expectedOut) }) }) }) }
func TestCreationOfZData(t *testing.T) { const n = 20 seg, _ := zdataFilledSegment(n) text := CapnpDecodeSegment(seg, "", "aircraftlib/aircraft.capnp", "Z") expectedText := `(zdata = (data = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13"))` cv.Convey("Given a go-capnproto created Zdata DATA element with n=20", t, func() { cv.Convey("When we decode it with capnp", func() { cv.Convey(fmt.Sprintf("Then we should get the expected text '%s'", expectedText), func() { cv.So(text, cv.ShouldEqual, expectedText) }) cv.Convey("And our data should contain Z_ZDATA with contents 0,1,2,...,n", func() { z := air.ReadRootZ(seg) cv.So(z.Which(), cv.ShouldEqual, air.Z_ZDATA) var data []byte = z.Zdata().Data() cv.So(len(data), cv.ShouldEqual, n) for i := range data { cv.So(data[i], cv.ShouldEqual, i) } }) }) }) }
func TestWebGoesUpAndDown(t *testing.T) { // *** universal test cfg setup skipbye := false cfg := NewTestConfig() // bumps cfg.TestportBump so cfg.GetWebPort() is different in test. defer cfg.ByeTestConfig(&skipbye) // *** end universal test setup s := NewWebServer() cv.Convey("NewWebServer() should bring up a debug web-server", t, func() { cv.So(PortIsBound(s.Addr), cv.ShouldEqual, true) by, err := FetchUrl("http://" + s.Addr + "/debug/pprof") cv.So(err, cv.ShouldEqual, nil) //fmt.Printf("by:'%s'\n", string(by)) cv.So(strings.HasPrefix(string(by), `<html> <head> <title>/debug/pprof/</title> </head> /debug/pprof/<br> <br>`), cv.ShouldEqual, true) }) cv.Convey("WebServer::Stop() should bring down the debug web-server", t, func() { s.Stop() cv.So(PortIsBound(s.Addr), cv.ShouldEqual, false) }) }
func TestDiffB(t *testing.T) { cv.Convey("Given two different (possibly long, differing in whitespace) strings a and b", t, func() { cv.Convey("then DiffB(a, b) should return the output of diff -b to consisely summarize their differences", func() { a := ` 1 2 3 4 5 type s1 struct { MyInts []int }` b := ` 1 2 3 4 type s1 struct { MyInts []int }` cv.So(string(Diffb(a, b)), cv.ShouldEqual, `6d5 < 5 `) }) }) }
func Test002ListListStructList(t *testing.T) { cv.Convey("Given type RWTest struct { NestMatrix [][]Nester1; } in go, where Nester1 is a struct, and a mirror/parallel capnp struct air.RWTestCapn { nestMatrix @0: List(List(Nester1Capn)); } defined in the aircraftlib schema", t, func() { cv.Convey("When we Save() RWTest to capn and then Load() it back, the data should match, so that we have working List(List(Struct)) serialization and deserializatoin in go-capnproto", func() { // full RWTest rw := RWTest{ NestMatrix: [][]Nester1{[]Nester1{Nester1{Strs: []string{"z", "w"}}, Nester1{Strs: []string{"q", "r"}}}, []Nester1{Nester1{Strs: []string{"zebra", "wally"}}, Nester1{Strs: []string{"qubert", "rocks"}}}}, } var o bytes.Buffer rw.Save(&o) seg, n, err := capn.ReadFromMemoryZeroCopy(o.Bytes()) cv.So(err, cv.ShouldEqual, nil) cv.So(n, cv.ShouldBeGreaterThan, 0) text := CapnpDecodeSegment(seg, "", "aircraftlib/aircraft.capnp", "RWTestCapn") if false { fmt.Printf("text = '%s'\n", text) } rw2 := &RWTest{} rw2.Load(&o) //fmt.Printf("rw = '%#v'\n", rw) //fmt.Printf("rw2 = '%#v'\n", rw2) same := reflect.DeepEqual(&rw, rw2) cv.So(same, cv.ShouldEqual, true) }) }) }
// start with smaller Struct(List) func Test001StructList(t *testing.T) { cv.Convey("Given type Nester1 struct { Strs []string } in go, where Nester1 is a struct, and a mirror/parallel capnp struct air.Nester1Capn { strs @0: List(Text); } defined in the aircraftlib schema", t, func() { cv.Convey("When we Save() Nester to capn and then Load() it back, the data should match, so that we have working Struct(List) serialization and deserializatoin in go-capnproto", func() { // Does Nester1 alone serialization and deser okay? rw := Nester1{Strs: []string{"xenophilia", "watchowski"}} var o bytes.Buffer rw.Save(&o) seg, n, err := capn.ReadFromMemoryZeroCopy(o.Bytes()) cv.So(err, cv.ShouldEqual, nil) cv.So(n, cv.ShouldBeGreaterThan, 0) text := CapnpDecodeSegment(seg, "", "aircraftlib/aircraft.capnp", "Nester1Capn") if false { fmt.Printf("text = '%s'\n", text) } rw2 := &Nester1{} rw2.Load(&o) //fmt.Printf("rw = '%#v'\n", rw) //fmt.Printf("rw2 = '%#v'\n", rw2) same := reflect.DeepEqual(&rw, rw2) cv.So(same, cv.ShouldEqual, true) }) }) }
func TestTextContaintingStruct(t *testing.T) { zjobBytes := CapnpEncode(`(cmd = "abc")`, "Zjob") cv.Convey("Given a simple struct message Zjob containing a string 'abc' and a list of string (empty)", t, func() { cv.Convey("then the go-capnproto serialization should match the capnp c++ serialization", func() { seg := capn.NewBuffer(nil) zjob := air.NewRootZjob(seg) zjob.SetCmd("abc") buf := bytes.Buffer{} seg.WriteTo(&buf) act := buf.Bytes() fmt.Printf(" actual:\n") ShowBytes(act, 10) fmt.Printf("\n\n expected:\n") ShowBytes(zjobBytes, 10) cv.So(act, cv.ShouldResemble, zjobBytes) }) }) }
func TestWriteBitListTwo64BitWords(t *testing.T) { seg := capn.NewBuffer(nil) z := air.NewRootZ(seg) list := seg.NewBitList(66) list.Set(64, true) list.Set(65, true) z.SetBoolvec(list) buf := bytes.Buffer{} seg.WriteTo(&buf) cv.Convey("Given a go-capnproto created List(Bool) Z::boolvec with bool values [true (+ 64 more times)]", t, func() { cv.Convey("Decoding it with c++ capnp should yield the expected text", func() { cv.So(CapnpDecodeSegment(seg, "", "aircraftlib/aircraft.capnp", "Z"), cv.ShouldEqual, `(boolvec = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true])`) }) }) cv.Convey("And we should be able to read back what we wrote", t, func() { z := air.ReadRootZ(seg) cv.So(z.Which(), cv.ShouldEqual, air.Z_BOOLVEC) var bitlist = z.Boolvec() cv.So(bitlist.Len(), cv.ShouldEqual, 66) for i := 0; i < 64; i++ { cv.So(bitlist.At(i), cv.ShouldEqual, false) } cv.So(bitlist.At(64), cv.ShouldEqual, true) cv.So(bitlist.At(65), cv.ShouldEqual, true) }) }
func TestWorkerSubmitPortAllocation(t *testing.T) { cv.Convey("qzub submit and workers should allocate their own port numbers to avoid conflicts", t, func() { cv.Convey(" so that we can run lots of workers and submits on the same machine if need be", func() { }) }) }
func TestUnMarshal(t *testing.T) { cv.Convey("Given go structs", t, func() { cv.Convey("then the generated Unmarshal() code should copy from the capnp into the go structs", func() { }) }) }
func TestObjectWithListOfTextBetweenSegments(t *testing.T) { exp := CapnpEncode(`(counter = (size = 9, wordlist = ["hello","bye"]))`, "Bag") cv.Convey("Given an Counter in one segment and a Bag with text in another", t, func() { cv.Convey("we should be able to copy from one segment to the other with SetCounter() on a Bag", func() { seg := capn.NewBuffer(nil) scratch := capn.NewBuffer(nil) // in seg segbag := air.NewRootBag(seg) // in scratch xc := air.NewRootCounter(scratch) xc.SetSize(9) tl := scratch.NewTextList(2) tl.Set(0, "hello") tl.Set(1, "bye") xc.SetWordlist(tl) xbuf := bytes.Buffer{} scratch.WriteTo(&xbuf) x := xbuf.Bytes() save(x, "myscratch") fmt.Printf("scratch segment (%p):\n", scratch) ShowBytes(x, 10) fmt.Printf("scratch segment (%p) with Counter decoded by capnp: '%s'\n", scratch, string(CapnpDecode(x, "Counter"))) prebuf := bytes.Buffer{} seg.WriteTo(&prebuf) fmt.Printf("Bag only segment seg (%p), pre-transfer:\n", seg) ShowBytes(prebuf.Bytes(), 10) // now for the actual test: // copy from scratch to seg segbag.SetCounter(xc) buf := bytes.Buffer{} seg.WriteTo(&buf) act := buf.Bytes() save(act, "myact") save(exp, "myexp") fmt.Printf("expected:\n") ShowBytes(exp, 10) fmt.Printf("exp decoded by capnp: '%s'\n", string(CapnpDecode(exp, "Bag"))) fmt.Printf(" actual:\n") ShowBytes(act, 10) fmt.Printf("act decoded by capnp: '%s'\n", string(CapnpDecode(act, "Bag"))) cv.So(act, cv.ShouldResemble, exp) }) }) }
func TestDataVersioningZeroPointersToMore(t *testing.T) { expEmpty := CapnpEncode("(mylist = [(),()])", "HoldsVerEmptyList") cv.Convey("Given a struct with 0 ptr fields, and a newer version of the struct with 1-2 pointer fields", t, func() { cv.Convey("then serializing the empty list and reading it back into 1 or 2 pointer fields should default initialize the pointer fields", func() { seg := capn.NewBuffer(nil) scratch := capn.NewBuffer(nil) emptyholder := air.NewRootHoldsVerEmptyList(seg) elist := air.NewVerEmptyList(scratch, 2) emptyholder.SetMylist(elist) actEmpty := ShowSeg(" after NewRootHoldsVerEmptyList(seg) and SetMylist(elist), segment seg is:", seg) actEmptyCap := string(CapnpDecode(actEmpty, "HoldsVerEmptyList")) expEmptyCap := string(CapnpDecode(expEmpty, "HoldsVerEmptyList")) cv.So(actEmptyCap, cv.ShouldResemble, expEmptyCap) fmt.Printf("\n actEmpty is \n") ShowBytes(actEmpty, 10) fmt.Printf("actEmpty decoded by capnp: '%s'\n", string(CapnpDecode(actEmpty, "HoldsVerEmptyList"))) cv.So(actEmpty, cv.ShouldResemble, expEmpty) // seg is set, now read into bigger list buf := bytes.Buffer{} seg.WriteTo(&buf) segbytes := buf.Bytes() reseg, _, err := capn.ReadFromMemoryZeroCopy(segbytes) if err != nil { panic(err) } ShowSeg(" after re-reading segbytes, segment reseg is:", reseg) fmt.Printf("segbytes decoded by capnp as HoldsVerOneDataList: '%s'\n", string(CapnpDecode(segbytes, "HoldsVerOneDataList"))) reHolder := air.ReadRootHoldsVerTwoTwoList(reseg) list22 := reHolder.Mylist() len22 := list22.Len() cv.So(len22, cv.ShouldEqual, 2) for i := 0; i < 2; i++ { ele := list22.At(i) val := ele.Val() cv.So(val, cv.ShouldEqual, 0) duo := ele.Duo() cv.So(duo, cv.ShouldEqual, 0) ptr1 := ele.Ptr1() ptr2 := ele.Ptr2() fmt.Printf("ptr1 = %#v\n", ptr1) cv.So(ptr1.Segment, cv.ShouldEqual, nil) fmt.Printf("ptr2 = %#v\n", ptr2) cv.So(ptr2.Segment, cv.ShouldEqual, nil) } }) }) }
func TestSheparding(t *testing.T) { // *** universal test cfg setup skipbye := false cfg := NewTestConfig() defer cfg.ByeTestConfig(&skipbye) // *** end universal test setup w := HelperNewWorkerDontStart(cfg) // Only pass t into top-level Convey calls cv.Convey("goq should be able to shepard a shell process", t, func() { cv.Convey("then stdout/stderr should be returned, without crashing the shepard ", func() { j := NewJob() j.Cmd = "./bin/badboy.sh" j.Workeraddr = w.Addr j.Serveraddr = w.ServerAddr w.Shepard(j) <-w.ShepSaysJobStarted j = <-w.ShepSaysJobDone fmt.Printf("\n\n j.Out = %#v\n", j.Out) cv.So(len(j.Out), cv.ShouldEqual, 2) cv.So(j.Out[0], cv.ShouldEqual, "some stderr") cv.So(j.Out[1], cv.ShouldEqual, "some stdout") }) cv.Convey("then segfaulting process should be handled ", func() { j := NewJob() j.Cmd = "./bin/faulter" w.Shepard(j) <-w.ShepSaysJobStarted j = <-w.ShepSaysJobDone cv.So(len(j.Out), cv.ShouldEqual, 2) expected := "Shepard finds non-nil err on trying to Wait() on cmd './bin/faulter' in dir ''" cv.So(j.Out[1][:len(expected)], cv.ShouldEqual, expected) }) cv.Convey("then executable file not found errors should be handled ", func() { j := NewJob() j.Cmd = "./does-not-exist" w.Shepard(j) <-w.ShepSaysJobStarted j = <-w.ShepSaysJobDone cv.So(len(j.Out), cv.ShouldEqual, 2) //cv.So(j.Out[0], cv.ShouldEqual, "") expectedSuffix := `Shepard finds non-nil err on trying to Wait() on cmd './does-not-exist' in dir ''` cv.So(strings.HasPrefix(j.Out[1], expectedSuffix), cv.ShouldEqual, true) }) }) }
func TestMarshal(t *testing.T) { cv.Convey("Given go struct Extra", t, func() { cv.Convey("then the generated ExtraCapntoGo() code should copy content from an ExtraCapn to an Extra struct.", func() { cv.Convey("and should handle int fields", func() { ex0 := ` type Extra struct { A int B int }` toGoCode := ExtractCapnToGoCode(ex0, "Extra") cv.So(toGoCode, ShouldMatchModuloWhiteSpace, ` func ExtraCapnToGo(src ExtraCapn, dest *Extra) *Extra { if dest == nil { dest = &Extra{} } dest.A = int(src.A()) dest.B = int(src.B()) return dest } `) toCapnCode := ExtractGoToCapnCode(ex0, "Extra") cv.So(toCapnCode, ShouldMatchModuloWhiteSpace, ` func ExtraGoToCapn(seg *capn.Segment, src *Extra) ExtraCapn { dest := AutoNewExtraCapn(seg) dest.SetA(int64(src.A)) dest.SetB(int64(src.B)) return dest } `) }) cv.Convey("and should handle uint fields", func() { ex0 := ` type Extra struct { A uint64 }` toGoCode := ExtractCapnToGoCode(ex0, "Extra") cv.So(toGoCode, ShouldMatchModuloWhiteSpace, ` func ExtraCapnToGo(src ExtraCapn, dest *Extra) *Extra { if dest == nil { dest = &Extra{} } dest.A = src.A() return dest } `) toCapnCode := ExtractGoToCapnCode(ex0, "Extra") cv.So(toCapnCode, ShouldMatchModuloWhiteSpace, ` func ExtraGoToCapn(seg *capn.Segment, src *Extra) ExtraCapn { dest := AutoNewExtraCapn(seg) dest.SetA(src.A) return dest } `) }) }) }) }
func TestLowercaseGoFieldsIgnoredByDefault(t *testing.T) { cv.Convey("Given the traditional golang std lib behvaior of not serializing lowercase fields,", t, func() { cv.Convey("then by default we should ignore lower case fields in writing the capnproto schema.", func() { ex0 := "type S struct { a string; B string \n}" cv.So(ExtractString2String(ex0), ShouldStartWithModuloWhiteSpace, `struct SCapn { b @0: Text; } `) }) }) }
func TestDefaultStructField(t *testing.T) { cv.Convey("Given a new root StackingRoot", t, func() { cv.Convey("then the aWithDefault field should have a default", func() { seg := capn.NewBuffer(nil) root := air.NewRootStackingRoot(seg) cv.So(root.AWithDefault().Num(), cv.ShouldEqual, 42) }) }) }
func TestSubmitRemote(t *testing.T) { cv.Convey("remotely, over nanomsg, goq should be able to submit job to the server", t, func() { cv.Convey("and then server should get back the expected output from the job run", func() { // allow all child processes to communicate // *** universal test cfg setup skipbye := false cfg := NewTestConfig() defer cfg.ByeTestConfig(&skipbye) // *** end universal test setup // ensure any previous test has released our port before proceeding. WaitUntilAddrAvailable(cfg.JservAddr()) cfg.DebugMode = true childpid, err := NewExternalJobServ(cfg) if err != nil { panic(err) } fmt.Printf("[pid %d] spawned a new external JobServ with pid %d\n", os.Getpid(), childpid) j := NewJob() j.Cmd = "bin/good.sh" sub, err := NewSubmitter(GenAddress(), cfg, false) if err != nil { panic(err) } sub.SubmitJob(j) worker, err := NewWorker(GenAddress(), cfg, nil) if err != nil { panic(err) } jobout, err := worker.DoOneJob() if err != nil { panic(err) } worker.Destroy() // *important* cleanup, and wait for cleanup to finish, so the next test can run. // has no Fromaddr, so crashes: SendShutdown(cfg.JservAddr, cfg) sub.SubmitShutdownJob() WaitForShutdownWithTimeout(childpid, cfg) cv.So(len(jobout.Out), cv.ShouldEqual, 2) cv.So(jobout.Out[0], cv.ShouldEqual, "I'm starting some work") cv.So(jobout.Out[1], cv.ShouldEqual, "I'm done with my work") }) }) }
func TestZserverWithAccessors(t *testing.T) { exp := CapnpEncode(`(waitingjobs = [(cmd = "abc"), (cmd = "xyz")])`, "Zserver") cv.Convey("Given an Zserver with a custom list", t, func() { cv.Convey("then all the accessors should work as expected", func() { seg := capn.NewBuffer(nil) scratch := capn.NewBuffer(nil) server := air.NewRootZserver(seg) joblist := air.NewZjobList(seg, 2) // .Set(int, item) zjob := air.NewZjob(scratch) zjob.SetCmd("abc") joblist.Set(0, zjob) zjob = air.NewZjob(scratch) zjob.SetCmd("xyz") joblist.Set(1, zjob) // .At(int) cv.So(joblist.At(0).Cmd(), cv.ShouldEqual, "abc") cv.So(joblist.At(1).Cmd(), cv.ShouldEqual, "xyz") // .Len() cv.So(joblist.Len(), cv.ShouldEqual, 2) // .ToArray() cv.So(len(joblist.ToArray()), cv.ShouldEqual, 2) cv.So(joblist.ToArray()[0].Cmd(), cv.ShouldEqual, "abc") cv.So(joblist.ToArray()[1].Cmd(), cv.ShouldEqual, "xyz") server.SetWaitingjobs(joblist) buf := bytes.Buffer{} seg.WriteTo(&buf) act := buf.Bytes() fmt.Printf(" actual:\n") ShowBytes(act, 10) fmt.Printf("act decoded by capnp: '%s'\n", string(CapnpDecode(act, "Zserver"))) save(act, "myact") fmt.Printf("expected:\n") ShowBytes(exp, 10) fmt.Printf("exp decoded by capnp: '%s'\n", string(CapnpDecode(exp, "Zserver"))) save(exp, "myexp") cv.So(act, cv.ShouldResemble, exp) }) }) }
func TestSubmitShutdownToRemoteJobServ(t *testing.T) { cv.Convey("remotely, over nanomsg, goq should be able to submit a shutdown job to the server", t, func() { cv.Convey("and then server process should shut itself down cleanly", func() { // *** universal test cfg setup skipbye := false cfg := NewTestConfig() defer cfg.ByeTestConfig(&skipbye) // *** end universal test setup jobservPid, err := NewExternalJobServ(cfg) if err != nil { fmt.Printf("\n Problem starting external job server! Is goq on your path? It must be. Do 'go install' first, then re-run this test.") panic(err) } fmt.Printf("\n[pid %d] spawned a new external JobServ with pid %d\n", os.Getpid(), jobservPid) // wait until process shows up in /proc t0 := time.Now() waited := 0 for { pt := *ProcessTable() _, jsAlive := pt[jobservPid] if jsAlive { break } time.Sleep(50 * time.Millisecond) waited++ VPrintf("cfg.SendTimeoutMsec = %v\n", cfg.SendTimeoutMsec) if time.Since(t0) > time.Millisecond*time.Duration(cfg.SendTimeoutMsec)*3 { panic(fmt.Sprintf("jobserv with expected pid %d did not show up in /proc after 3 recv timeouts", jobservPid)) } } fmt.Printf("\njobserv with expected pid %d was *found* in /proc after %d waits of 50msec\n", jobservPid, waited) // then kill it SendShutdown(cfg) fmt.Printf("\nsent shutdown request\n") // verify kill // non-deterministic, but try to give them time to be gone. WaitForShutdownWithTimeout(jobservPid, cfg) pt := *ProcessTable() _, jsAlive := pt[jobservPid] if jsAlive == false { fmt.Printf("jobserv at pid %d appears to have been shutdown by our comand.\n", jobservPid) } cv.So(jsAlive, cv.ShouldEqual, false) }) }) }
func TestTagAnnotationWorks(t *testing.T) { cv.Convey("Given a golang struct with an invalid capnp field name 'Union', but with a field tag: `capname:\"MyNewFieldName\"`", t, func() { cv.Convey("then we should use the capname MyNewFieldName for the field, and not stop the run.", func() { ex0 := "type S struct { Union string `capname:\"MyNewFieldName\"` \n}" cv.So(ExtractString2String(ex0), ShouldStartWithModuloWhiteSpace, `struct SCapn { MyNewFieldName @0: Text; } `) ex1 := "type S struct { Union string `capname: \t \t \"MyNewFieldName\"` \n}" cv.So(ExtractString2String(ex1), ShouldStartWithModuloWhiteSpace, `struct SCapn { MyNewFieldName @0: Text; } `) }) }) }
func TestTagCapidWorks(t *testing.T) { cv.Convey("Given the desire to preserve the field numbering in the generated Capnproto schema,", t, func() { cv.Convey("when we add the tag: capid:\"1\", then the field should be numbered @1.", func() { cv.Convey("and if there are fewer than 2 (numbered 0, 1) fields then we error out.", func() { ex0 := "type S struct { A string `capid:\"1\"`; B string \n}" cv.So(ExtractString2String(ex0), ShouldStartWithModuloWhiteSpace, `struct SCapn { b @0: Text; a @1: Text; } `) }) }) }) }
func TestEnumFromString(t *testing.T) { cv.Convey("Given an enum tag string matching a constant", t, func() { cv.Convey("FromString should return the corresponding matching constant value", func() { cv.So(air.AirportFromString("jfk"), cv.ShouldEqual, air.AIRPORT_JFK) }) }) cv.Convey("Given an enum tag string that does not match a constant", t, func() { cv.Convey("FromString should return 0", func() { cv.So(air.AirportFromString("notEverMatching"), cv.ShouldEqual, 0) }) }) }