CMertens / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

Wrapped linked list with a cycle is not properly deserialized #286

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

    public class Element
    {
        static private int counter = 0;
        private int id;

        public int Num;
        public Element Next;

        public Element()
        {
            id = counter;
            counter++;
        }
    }

    public class CircularList
    {
        public int Key = 0;

        public Element Root;
    }

    [TestMethod]
    public void TestCircularList()
    {
        var obj = new CircularList();

        obj.Root = new Element ();
        obj.Root.Num = 1;
        obj.Root.Next = new Element();
        obj.Root.Next.Num = 2;
        obj.Root.Next.Next = obj.Root;

        var model = TypeModel.Create();
        var topMeta = model.Add(typeof(CircularList), false);

        topMeta.Add(1, "Key");
        topMeta.Add(2, "Root");

        var elemMeta = model.Add(typeof(Element), false);
        elemMeta.AsReferenceDefault = true;

        elemMeta.Add(1, "Num");
        elemMeta.Add(2, "Next");

        model.CompileInPlace();

        using (var stream = new MemoryStream())
        {
            model.Serialize(stream, obj);

            stream.Position = 0;

            var resultObject = model.Deserialize(stream, null, typeof(CircularList)) as CircularList;

            Assert.AreSame(resultObject.Root, resultObject.Root.Next.Next);
        }
    }

What is the expected output? What do you see instead?

The assert should pass, but it fails. It looks like one extra element is 
generated in the resulting list and the cycle is shifted by one. The private id 
field should help to identify the Element objects.

this seems to work, if the list is not wrapped in another class. See the 
following test:

    [TestMethod]
    public void TestCircularRefs()
    {
        Element root = new Element();
        root.Num = 1;
        root.Next = new Element();
        root.Next.Num = 2;
        root.Next.Next = root;

        var model = TypeModel.Create();

        var elemMeta = model.Add(typeof(Element), false);
        elemMeta.AsReferenceDefault = true;

        elemMeta.Add(1, "Num");
        elemMeta.Add(2, "Next");

        model.CompileInPlace();

        using (var stream = new MemoryStream())
        {
            model.Serialize(stream, root);

            stream.Position = 0;

            var resultObject = model.Deserialize(stream, null, typeof(Element)) as Element;

            Assert.AreSame(resultObject, resultObject.Next.Next);
        }
    }

What version of the product are you using? On what operating system?

v2 Beta2 on Windows 7

Regards,
Slobodan

Original issue reported on code.google.com by s.m.boja...@gmail.com on 11 Apr 2012 at 11:21