Beispiel #1
0
func TestDataVersioningAvoidsUnnecessaryTruncation(t *testing.T) {

	expFull := CapnpEncode("(val = 9, duo = 8, ptr1 = (val = 77), ptr2 = (val = 55))", "VerTwoDataTwoPtr")
	//expEmpty := CapnpEncode("()", "VerEmpty")

	cv.Convey("Given a struct with 0 ptr fields, and a newer version of the struct with two data and two pointer fields", t, func() {
		cv.Convey("then old code expecting the smaller struct but reading the newer-bigger struct should not truncate it if it doesn't have to (e.g. not assigning into a composite list), and should preserve all data when re-serializing it.", func() {

			seg := capn.NewBuffer(nil)
			scratch := capn.NewBuffer(nil)

			big := air.NewRootVerTwoDataTwoPtr(seg)
			one := air.NewVerOneData(scratch)
			one.SetVal(77)
			two := air.NewVerOneData(scratch)
			two.SetVal(55)
			big.SetVal(9)
			big.SetDuo(8)
			big.SetPtr1(one)
			big.SetPtr2(two)

			bigVerBytes := ShowSeg("\n\n   with our 2x2 new big struct, segment seg is:", seg)

			cv.So(bigVerBytes, cv.ShouldResemble, expFull)

			// now pretend to be an old client, reading and writing
			// expecting an empty struct, but full data should be preserved
			// and written, because we aren't writing into a cramped/
			// fixed-space composite-list space.

			// Before test, verify that if we force reading into text-form, we get
			// what we expect.
			actEmptyCap := string(CapnpDecode(bigVerBytes, "VerEmpty"))
			cv.So(actEmptyCap, cv.ShouldResemble, "()\n")

			// okay, now the actual test:
			weThinkEmptyButActuallyFull := air.ReadRootVerEmpty(seg)

			freshSeg := capn.NewBuffer(nil)
			wrapEmpty := air.NewRootWrapEmpty(freshSeg)

			// here is the critical step, this should not truncate:
			wrapEmpty.SetMightNotBeReallyEmpty(weThinkEmptyButActuallyFull)

			// now verify:
			freshBytes := ShowSeg("\n\n          after wrapEmpty.SetMightNotBeReallyEmpty(weThinkEmptyButActuallyFull), segment freshSeg is:", freshSeg)

			reseg, _, err := capn.ReadFromMemoryZeroCopy(freshBytes)
			if err != nil {
				panic(err)
			}
			ShowSeg("      after re-reading freshBytes, segment reseg is:", reseg)
			fmt.Printf("freshBytes decoded by capnp as Wrap2x2: '%s'\n", string(CapnpDecode(freshBytes, "Wrap2x2")))

			wrap22 := air.ReadRootWrap2x2plus(reseg)
			notEmpty := wrap22.MightNotBeReallyEmpty()
			val := notEmpty.Val()
			cv.So(val, cv.ShouldEqual, 9)
			duo := notEmpty.Duo()
			cv.So(duo, cv.ShouldEqual, 8)
			ptr1 := notEmpty.Ptr1()
			ptr2 := notEmpty.Ptr2()
			cv.So(ptr1.Val(), cv.ShouldEqual, 77)
			cv.So(ptr2.Val(), cv.ShouldEqual, 55)
			// Tre should get the default, as it was never set
			cv.So(notEmpty.Tre(), cv.ShouldEqual, 0)
			// same for Lst3
			cv.So(notEmpty.Lst3().Len(), cv.ShouldEqual, 0)
		})
	})
}
Beispiel #2
0
func TestDataVersioningZeroPointersToTwo(t *testing.T) {
	cv.Convey("Given a struct with 2 ptr fields, and another version of the struct with 0 or 1 pointer fields", t, func() {
		cv.Convey("then reading serialized bigger-struct-list into the smaller (empty or one data-pointer) list should work, truncating/ignoring the new fields", func() {

			seg := capn.NewBuffer(nil)
			scratch := capn.NewBuffer(nil)
			holder := air.NewRootHoldsVerTwoTwoList(seg)

			twolist := air.NewVerTwoDataTwoPtrList(scratch, 2)
			plist := capn.PointerList(twolist)

			d0 := air.NewVerTwoDataTwoPtr(scratch)
			d0.SetVal(27)
			d0.SetDuo(26)

			v1 := air.NewVerOneData(scratch)
			v1.SetVal(25)
			v2 := air.NewVerOneData(scratch)
			v2.SetVal(23)

			d0.SetPtr1(v1)
			d0.SetPtr2(v2)

			d1 := air.NewVerTwoDataTwoPtr(scratch)
			d1.SetVal(42)
			d1.SetDuo(41)

			w1 := air.NewVerOneData(scratch)
			w1.SetVal(40)
			w2 := air.NewVerOneData(scratch)
			w2.SetVal(38)

			d1.SetPtr1(w1)
			d1.SetPtr2(w2)

			plist.Set(0, capn.Object(d0))
			plist.Set(1, capn.Object(d1))

			holder.SetMylist(twolist)

			ShowSeg("     before serializing out, segment scratch is:", scratch)
			ShowSeg("     before serializing out, segment seg is:", seg)

			// serialize out
			buf := bytes.Buffer{}
			seg.WriteTo(&buf)
			segbytes := buf.Bytes()

			// and read-back in using smaller expectations
			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 HoldsVerEmptyList: '%s'\n", string(CapnpDecode(segbytes, "HoldsVerEmptyList")))
			fmt.Printf("segbytes decoded by capnp as HoldsVerOnePtrList: '%s'\n", string(CapnpDecode(segbytes, "HoldsVerOnePtrList")))
			fmt.Printf("segbytes decoded by capnp as HoldsVerTwoTwoList: '%s'\n", string(CapnpDecode(segbytes, "HoldsVerTwoTwoList")))

			reHolder := air.ReadRootHoldsVerEmptyList(reseg)
			elist := reHolder.Mylist()
			lene := elist.Len()
			cv.So(lene, cv.ShouldEqual, 2)

			reHolder1 := air.ReadRootHoldsVerOnePtrList(reseg)
			onelist := reHolder1.Mylist()
			lenone := onelist.Len()
			cv.So(lenone, cv.ShouldEqual, 2)

			for i := 0; i < 2; i++ {
				ele := onelist.At(i)
				ptr1 := ele.Ptr()
				cv.So(ptr1.Val(), cv.ShouldEqual, twolist.At(i).Ptr1().Val())
			}

			reHolder2 := air.ReadRootHoldsVerTwoTwoPlus(reseg)
			twolist2 := reHolder2.Mylist()
			lentwo2 := twolist2.Len()
			cv.So(lentwo2, cv.ShouldEqual, 2)

			for i := 0; i < 2; i++ {
				ele := twolist2.At(i)
				ptr1 := ele.Ptr1()
				ptr2 := ele.Ptr2()
				cv.So(ptr1.Val(), cv.ShouldEqual, twolist.At(i).Ptr1().Val())
				//cv.So(ptr1.Duo(), cv.ShouldEqual, twolist.At(i).Ptr1().Duo())
				cv.So(ptr2.Val(), cv.ShouldEqual, twolist.At(i).Ptr2().Val())
				//cv.So(ptr2.Duo(), cv.ShouldEqual, twolist.At(i).Ptr2().Duo())
				cv.So(ele.Tre(), cv.ShouldEqual, 0)
				cv.So(ele.Lst3().Len(), cv.ShouldEqual, 0)
			}

		})
	})
}