1 /*
2  * Copyright 2016-17, OpenCensus Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.opencensus.implcore.tags.propagation;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import com.google.common.base.Charsets;
22 import com.google.common.collect.Collections2;
23 import io.opencensus.implcore.internal.VarInt;
24 import io.opencensus.implcore.tags.TagsComponentImplBase;
25 import io.opencensus.tags.Tag;
26 import io.opencensus.tags.TagContext;
27 import io.opencensus.tags.TagContextBuilder;
28 import io.opencensus.tags.TagKey;
29 import io.opencensus.tags.TagValue;
30 import io.opencensus.tags.Tagger;
31 import io.opencensus.tags.TagsComponent;
32 import io.opencensus.tags.propagation.TagContextBinarySerializer;
33 import io.opencensus.tags.propagation.TagContextSerializationException;
34 import java.io.ByteArrayOutputStream;
35 import java.io.IOException;
36 import java.util.Arrays;
37 import java.util.Collection;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Set;
41 import org.junit.Rule;
42 import org.junit.Test;
43 import org.junit.rules.ExpectedException;
44 import org.junit.runner.RunWith;
45 import org.junit.runners.JUnit4;
46 
47 /**
48  * Tests for serializing tags with {@link BinarySerializationUtils} and {@link
49  * TagContextBinarySerializerImpl}.
50  */
51 @RunWith(JUnit4.class)
52 public class TagContextSerializationTest {
53 
54   @Rule public final ExpectedException thrown = ExpectedException.none();
55 
56   private static final TagKey K1 = TagKey.create("k1");
57   private static final TagKey K2 = TagKey.create("k2");
58   private static final TagKey K3 = TagKey.create("k3");
59   private static final TagKey K4 = TagKey.create("k4");
60 
61   private static final TagValue V1 = TagValue.create("v1");
62   private static final TagValue V2 = TagValue.create("v2");
63   private static final TagValue V3 = TagValue.create("v3");
64   private static final TagValue V4 = TagValue.create("v4");
65 
66   private static final Tag T1 = Tag.create(K1, V1);
67   private static final Tag T2 = Tag.create(K2, V2);
68   private static final Tag T3 = Tag.create(K3, V3);
69   private static final Tag T4 = Tag.create(K4, V4);
70 
71   private final TagsComponent tagsComponent = new TagsComponentImplBase();
72   private final TagContextBinarySerializer serializer =
73       tagsComponent.getTagPropagationComponent().getBinarySerializer();
74   private final Tagger tagger = tagsComponent.getTagger();
75 
76   @Test
testSerializeDefault()77   public void testSerializeDefault() throws Exception {
78     testSerialize();
79   }
80 
81   @Test
testSerializeWithOneTag()82   public void testSerializeWithOneTag() throws Exception {
83     testSerialize(T1);
84   }
85 
86   @Test
testSerializeWithMultipleTags()87   public void testSerializeWithMultipleTags() throws Exception {
88     testSerialize(T1, T2, T3, T4);
89   }
90 
91   @Test
testSerializeTooLargeTagContext()92   public void testSerializeTooLargeTagContext() throws TagContextSerializationException {
93     TagContextBuilder builder = tagger.emptyBuilder();
94     for (int i = 0; i < BinarySerializationUtils.TAGCONTEXT_SERIALIZED_SIZE_LIMIT / 8 - 1; i++) {
95       // Each tag will be with format {key : "0123", value : "0123"}, so the length of it is 8.
96       String str;
97       if (i < 10) {
98         str = "000" + i;
99       } else if (i < 100) {
100         str = "00" + i;
101       } else if (i < 1000) {
102         str = "0" + i;
103       } else {
104         str = String.valueOf(i);
105       }
106       builder.put(TagKey.create(str), TagValue.create(str));
107     }
108     // The last tag will be of size 9, so the total size of the TagContext (8193) will be one byte
109     // more than limit.
110     builder.put(TagKey.create("last"), TagValue.create("last1"));
111 
112     TagContext tagContext = builder.build();
113     thrown.expect(TagContextSerializationException.class);
114     thrown.expectMessage("Size of TagContext exceeds the maximum serialized size ");
115     serializer.toByteArray(tagContext);
116   }
117 
testSerialize(Tag... tags)118   private void testSerialize(Tag... tags) throws IOException, TagContextSerializationException {
119     TagContextBuilder builder = tagger.emptyBuilder();
120     for (Tag tag : tags) {
121       builder.put(tag.getKey(), tag.getValue());
122     }
123 
124     byte[] actual = serializer.toByteArray(builder.build());
125 
126     Collection<List<Tag>> tagPermutation = Collections2.permutations(Arrays.asList(tags));
127     Set<String> possibleOutputs = new HashSet<String>();
128     for (List<Tag> list : tagPermutation) {
129       ByteArrayOutputStream expected = new ByteArrayOutputStream();
130       expected.write(BinarySerializationUtils.VERSION_ID);
131       for (Tag tag : list) {
132         expected.write(BinarySerializationUtils.TAG_FIELD_ID);
133         encodeString(tag.getKey().getName(), expected);
134         encodeString(tag.getValue().asString(), expected);
135       }
136       possibleOutputs.add(new String(expected.toByteArray(), Charsets.UTF_8));
137     }
138 
139     assertThat(possibleOutputs).contains(new String(actual, Charsets.UTF_8));
140   }
141 
encodeString(String input, ByteArrayOutputStream byteArrayOutputStream)142   private static void encodeString(String input, ByteArrayOutputStream byteArrayOutputStream)
143       throws IOException {
144     VarInt.putVarInt(input.length(), byteArrayOutputStream);
145     byteArrayOutputStream.write(input.getBytes(Charsets.UTF_8));
146   }
147 }
148