aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/test/java/com/yahoo/document/serialization/VespaDocumentSerializerTestCase.java
blob: 4f34431c7297343939e3c97ba8a2e0f9136c6bf7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.document.serialization;

import com.yahoo.compress.CompressionType;
import com.yahoo.compress.Compressor;
import com.yahoo.document.CompressionConfig;
import com.yahoo.document.DataType;
import com.yahoo.document.Document;
import com.yahoo.document.DocumentType;
import com.yahoo.document.DocumentTypeManager;
import com.yahoo.document.Field;
import com.yahoo.document.MapDataType;
import com.yahoo.document.StructDataType;
import com.yahoo.document.datatypes.IntegerFieldValue;
import com.yahoo.document.datatypes.MapFieldValue;
import com.yahoo.document.datatypes.PredicateFieldValue;
import com.yahoo.document.datatypes.StringFieldValue;
import com.yahoo.document.datatypes.Struct;
import com.yahoo.io.GrowableByteBuffer;
import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * @author Simon Thoresen Hult
 * @author vekterli
 */
@SuppressWarnings("deprecation")
public class VespaDocumentSerializerTestCase {

    @Test
    public void get_serialized_size_uses_latest_serializer() {
        DocumentType docType = new DocumentType("my_type");
        docType.addField("my_str", DataType.STRING);
        docType.addField("my_int", DataType.INT);
        Document doc = new Document(docType, "doc:scheme:");
        doc.setFieldValue("my_str", new StringFieldValue("foo"));
        doc.setFieldValue("my_int", new IntegerFieldValue(69));

        GrowableByteBuffer buf = new GrowableByteBuffer();
        doc.serialize(buf);
        assertEquals(buf.position(), VespaDocumentSerializer42.getSerializedSize(doc));
    }

    @Test
    public void predicate_field_values_are_serialized() {
        DocumentType docType = new DocumentType("my_type");
        Field field = new Field("my_predicate", DataType.PREDICATE);
        docType.addField(field);
        Document doc = new Document(docType, "doc:scheme:");
        PredicateFieldValue predicate = Mockito.mock(PredicateFieldValue.class);
        doc.setFieldValue("my_predicate", predicate);

        DocumentSerializerFactory.create42(new GrowableByteBuffer()).write(doc);
        Mockito.verify(predicate, Mockito.times(1)).serialize(Mockito.same(field), Mockito.any(FieldWriter.class));
    }

    static class CompressionFixture {

        static final String COMPRESSABLE_STRING = "zippy zip mc zippington the 3rd zippy zip";

        final DocumentTypeManager manager;
        final DocumentType docType;
        final StructDataType nestedType;
        final MapDataType mapType;

        CompressionFixture() {
            docType = new DocumentType("map_of_structs");
            docType.getHeaderType().setCompressionConfig(new CompressionConfig(CompressionType.LZ4));

            nestedType = new StructDataType("nested_type");
            nestedType.addField(new Field("str", DataType.STRING));

            mapType = new MapDataType(DataType.STRING, nestedType);
            docType.addField(new Field("map", mapType));

            manager = new DocumentTypeManager();
            manager.registerDocumentType(docType);
        }

        static GrowableByteBuffer asSerialized(Document inputDoc) {
            GrowableByteBuffer buf = new GrowableByteBuffer();
            inputDoc.serialize(buf);
            buf.flip();
            return buf;
        }

        Document roundtripSerialize(Document inputDoc) {
            return manager.createDocument(asSerialized(inputDoc));
        }
    }

    @Test
    public void compressed_map_of_compressed_structs_is_supported() {
        CompressionFixture fixture = new CompressionFixture();

        Document doc = new Document(fixture.docType, "id:foo:map_of_structs::flarn");
        Struct nested = new Struct(fixture.nestedType);
        nested.setFieldValue("str", new StringFieldValue(CompressionFixture.COMPRESSABLE_STRING));

        MapFieldValue<StringFieldValue, Struct> map = new MapFieldValue<StringFieldValue, Struct>(fixture.mapType);
        map.put(new StringFieldValue("foo"), nested);
        map.put(new StringFieldValue("bar"), nested);
        doc.setFieldValue("map", map);

        // Should _not_ throw any deserialization exceptions
        Document result = fixture.roundtripSerialize(doc);
        assertEquals(doc, result);
    }

    @Test
    public void incompressable_structs_are_serialized_without_buffer_size_overhead_bug() {
        CompressionFixture fixture = new CompressionFixture();

        Document doc = new Document(fixture.docType, "id:foo:map_of_structs::flarn");
        Struct nested = new Struct(fixture.nestedType);
        nested.setFieldValue("str", new StringFieldValue(CompressionFixture.COMPRESSABLE_STRING));

        MapFieldValue<StringFieldValue, Struct> map = new MapFieldValue<StringFieldValue, Struct>(fixture.mapType);
        // Only 1 struct added. Not enough redundant information that header struct containing map itself
        // can be compressed.
        map.put(new StringFieldValue("foo"), nested);
        doc.setFieldValue("map", map);

        GrowableByteBuffer buf = CompressionFixture.asSerialized(doc);
        // Explanation of arbitrary value: buffer copy bug meant that incompressable structs were all serialized
        // rounded up to 4096 bytes.
        assertTrue(buf.remaining() < 4096);
    }
}