/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.core.util;
import com.google.protobuf.ByteString;
import java.io.StringWriter;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.test.Test.Countries;
import org.sonar.core.test.Test.Country;
import org.sonar.core.test.Test.NestedMsg;
import org.sonar.core.test.Test.PrimitiveTypeMsg;
import org.sonar.core.test.Test.TestArray;
import org.sonar.core.test.Test.TestMap;
import org.sonar.core.test.Test.TestMapOfArray;
import org.sonar.core.test.Test.TestMapOfMap;
import org.sonar.core.test.Test.TestNullableArray;
import org.sonar.core.test.Test.TestNullableMap;
import org.sonar.core.test.Test.Translations;
import org.sonar.test.TestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.core.util.ProtobufJsonFormat.toJson;
public class ProtobufJsonFormatTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void test_primitive_types() {
PrimitiveTypeMsg protobuf = PrimitiveTypeMsg.newBuilder()
.setStringField("foo")
.setIntField(10)
.setLongField(100L)
.setDoubleField(3.14)
.setBooleanField(true)
.setEnumField(org.sonar.core.test.Test.FakeEnum.GREEN)
.build();
assertThat(toJson(protobuf)).isEqualTo(
"{\"stringField\":\"foo\",\"intField\":10,\"longField\":100,\"doubleField\":3.14,\"booleanField\":true,\"enumField\":\"GREEN\"}");
}
@Test
public void bytes_field_can_not_be_converted() {
expectedException.expect(RuntimeException.class);
expectedException.expectMessage("JSON format does not support type 'BYTE_STRING' of field 'bytesField'");
PrimitiveTypeMsg protobuf = PrimitiveTypeMsg.newBuilder()
.setBytesField(ByteString.copyFrom(new byte[]{2, 4}))
.build();
ProtobufJsonFormat.write(protobuf, JsonWriter.of(new StringWriter()));
}
@Test
public void do_not_write_null_primitive_fields() {
PrimitiveTypeMsg msg = PrimitiveTypeMsg.newBuilder().build();
// fields are absent
assertThat(msg.hasStringField()).isFalse();
assertThat(msg.hasIntField()).isFalse();
}
@Test
public void write_empty_string() {
PrimitiveTypeMsg msg = PrimitiveTypeMsg.newBuilder().setStringField("").build();
// field is present
assertThat(msg.hasStringField()).isTrue();
assertThat(msg.getStringField()).isEqualTo("");
assertThat(toJson(msg)).isEqualTo("{\"stringField\":\"\"}");
}
@Test
public void write_array() {
TestArray msg = TestArray.newBuilder()
.addStrings("one").addStrings("two")
.addNesteds(NestedMsg.newBuilder().setLabel("nestedOne")).addNesteds(NestedMsg.newBuilder().setLabel("nestedTwo"))
.build();
assertThat(toJson(msg))
.isEqualTo("{\"strings\":[\"one\",\"two\"],\"nesteds\":[{\"label\":\"nestedOne\"},{\"label\":\"nestedTwo\"}]}");
}
@Test
public void write_empty_array() {
TestArray msg = TestArray.newBuilder().build();
assertThat(toJson(msg)).isEqualTo("{\"strings\":[],\"nesteds\":[]}");
}
@Test
public void do_not_write_null_wrapper_of_array() {
TestNullableArray msg = TestNullableArray.newBuilder()
.setLabel("world")
.build();
assertThat(msg.hasCountries()).isFalse();
// array wrapper is null
assertThat(toJson(msg)).isEqualTo("{\"label\":\"world\"}");
}
@Test
public void inline_wrapper_of_array() {
TestNullableArray msg = TestNullableArray.newBuilder()
.setLabel("world")
.setCountries(Countries.newBuilder())
.build();
assertThat(msg.hasCountries()).isTrue();
assertThat(toJson(msg)).contains("\"label\":\"world\",\"countries\":[]");
msg = TestNullableArray.newBuilder()
.setLabel("world")
.setCountries(Countries.newBuilder().addCountries(Country.newBuilder().setName("France").setContinent("Europe")))
.build();
assertThat(msg.hasCountries()).isTrue();
assertThat(toJson(msg)).contains("\"label\":\"world\",\"countries\":[{\"name\":\"France\",\"continent\":\"Europe\"}]");
}
@Test
public void write_map() {
TestMap.Builder builder = TestMap.newBuilder();
builder.getMutableStringMap().put("one", "un");
builder.getMutableStringMap().put("two", "deux");
builder.getMutableNestedMap().put("three", NestedMsg.newBuilder().setLabel("trois").build());
builder.getMutableNestedMap().put("four", NestedMsg.newBuilder().setLabel("quatre").build());
assertThat(toJson(builder.build())).isEqualTo(
"{\"stringMap\":{\"one\":\"un\",\"two\":\"deux\"},\"nestedMap\":{\"three\":{\"label\":\"trois\"},\"four\":{\"label\":\"quatre\"}}}");
}
@Test
public void write_empty_map() {
TestMap.Builder builder = TestMap.newBuilder();
assertThat(toJson(builder.build())).isEqualTo("{\"stringMap\":{},\"nestedMap\":{}}");
}
@Test
public void do_not_write_null_wrapper_of_map() {
TestNullableMap msg = TestNullableMap.newBuilder()
.setLabel("world")
.build();
assertThat(toJson(msg)).isEqualTo("{\"label\":\"world\"}");
}
@Test
public void inline_wrapper_of_map() {
TestNullableMap msg = TestNullableMap.newBuilder()
.setLabel("world")
.setTranslations(Translations.newBuilder())
.build();
assertThat(toJson(msg)).isEqualTo("{\"label\":\"world\",\"translations\":{}}");
Translations.Builder translationsBuilder = Translations.newBuilder();
translationsBuilder.getMutableTranslations().put("one", "un");
translationsBuilder.getMutableTranslations().put("two", "deux");
msg = TestNullableMap.newBuilder()
.setLabel("world")
.setTranslations(translationsBuilder)
.build();
assertThat(toJson(msg)).isEqualTo("{\"label\":\"world\",\"translations\":{\"one\":\"un\",\"two\":\"deux\"}}");
}
@Test
public void write_map_of_arrays() throws Exception {
// this is a trick to have arrays in map values
TestMapOfArray.Builder msg = TestMapOfArray.newBuilder();
// wrapper over array
Countries europe = Countries.newBuilder()
.addCountries(Country.newBuilder().setContinent("Europe").setName("France"))
.addCountries(Country.newBuilder().setContinent("Europe").setName("Germany"))
.build();
msg.getMutableMoneys().put("eur", europe);
assertThat(toJson(msg.build())).isEqualTo("{\"moneys\":{\"eur\":[{\"name\":\"France\",\"continent\":\"Europe\"},{\"name\":\"Germany\",\"continent\":\"Europe\"}]}}");
}
@Test
public void write_map_of_map() throws Exception {
// this is a trick to have maps in map values
TestMapOfMap.Builder msg = TestMapOfMap.newBuilder();
// wrapper over map
Translations.Builder translationsBuilder = Translations.newBuilder();
translationsBuilder.getMutableTranslations().put("one", "un");
translationsBuilder.getMutableTranslations().put("two", "deux");
msg.getMutableCatalogs().put("numbers", translationsBuilder.build());
assertThat(toJson(msg.build())).isEqualTo("{\"catalogs\":{\"numbers\":{\"one\":\"un\",\"two\":\"deux\"}}}");
}
@Test
public void constructor_is_private() throws Exception {
assertThat(TestUtils.hasOnlyPrivateConstructors(ProtobufJsonFormat.class)).isTrue();
}
}