1 /* 2 * Copyright (C) 2019 The Android Open Source Project 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 com.google.tuningfork.validation; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static java.nio.charset.StandardCharsets.UTF_8; 21 import static org.junit.Assert.assertThrows; 22 23 import com.google.common.collect.Iterables; 24 import com.google.common.collect.Lists; 25 import com.google.common.io.Files; 26 import com.google.devtools.build.runtime.Runfiles; 27 import com.google.protobuf.DescriptorProtos.FileDescriptorSet; 28 import com.google.protobuf.Descriptors.Descriptor; 29 import com.google.protobuf.Descriptors.FileDescriptor; 30 import java.io.File; 31 import java.util.Arrays; 32 import java.util.List; 33 import java.util.Optional; 34 import org.junit.Before; 35 import org.junit.Rule; 36 import org.junit.Test; 37 import org.junit.rules.TemporaryFolder; 38 import org.junit.runner.RunWith; 39 import org.junit.runners.JUnit4; 40 41 @RunWith(JUnit4.class) 42 public final class ExternalProtoCompilerTest { 43 @Rule 44 // Override default behavior to allow overwriting files. 45 public TemporaryFolder tempFolder = 46 new TemporaryFolder() { 47 @Override 48 public File newFile(String filename) { 49 return new File(getRoot(), filename); 50 } 51 }; 52 53 private static final File PROTOC_BINARY = 54 Runfiles.location("net/proto2/compiler/public/protocol_compiler"); 55 56 private static List<String> defaultCommandLine; 57 private final ExternalProtoCompiler compiler = new ExternalProtoCompiler(PROTOC_BINARY); 58 private final TestdataHelper helper = new TestdataHelper(tempFolder); 59 60 @Before setUp()61 public void setUp() { 62 defaultCommandLine = Lists.newArrayList(); 63 defaultCommandLine.add(PROTOC_BINARY.getAbsolutePath()); 64 defaultCommandLine.add("-o"); 65 defaultCommandLine.add("/dev/stdout"); 66 } 67 68 @Test compileValid()69 public void compileValid() throws Exception { 70 File file = helper.getFile("compile_valid.proto"); 71 72 FileDescriptor fDesc = compiler.compile(file, Optional.empty()); 73 74 Descriptor messageDesc = fDesc.findMessageTypeByName("Message"); 75 Descriptor anotherDesc = fDesc.findMessageTypeByName("AnotherMessage"); 76 assertThat(messageDesc).isNotNull(); 77 assertThat(anotherDesc).isNotNull(); 78 } 79 80 @Test compareDescriptors()81 public void compareDescriptors() throws Exception { 82 File file = helper.getFile("compile_valid.proto"); 83 File outFile = new File(tempFolder.getRoot(), "compile_valid.descriptor"); 84 85 FileDescriptor stdoutDescriptor = compiler.compile(file, Optional.of(outFile)); 86 87 Descriptor messageDesc = stdoutDescriptor.findMessageTypeByName("Message"); 88 Descriptor anotherDesc = stdoutDescriptor.findMessageTypeByName("AnotherMessage"); 89 FileDescriptorSet fileSet = FileDescriptorSet.parseFrom(Files.toByteArray(outFile)); 90 FileDescriptor outFileDescriptor = 91 FileDescriptor.buildFrom( 92 Iterables.getOnlyElement(fileSet.getFileList()), new FileDescriptor[] {}); 93 94 assertThat(messageDesc).isNotNull(); 95 assertThat(anotherDesc).isNotNull(); 96 assertThat(outFile).isNotNull(); 97 assertThat(stdoutDescriptor.toProto()).isEqualTo(outFileDescriptor.toProto()); 98 } 99 100 @Test compileInvalid()101 public void compileInvalid() throws Exception { 102 File file = helper.getFile("compile_invalid.proto"); 103 CompilationException expected = 104 assertThrows(CompilationException.class, () -> compiler.compile(file, Optional.empty())); 105 106 assertThat(expected) 107 .hasMessageThat() 108 .isEqualTo("Descriptor for [compile_invalid.proto] does not exist."); 109 } 110 111 @Test compileWithDeps()112 public void compileWithDeps() throws Exception { 113 File file = helper.getFile("compile_with_deps.proto"); 114 CompilationException expected = 115 assertThrows(CompilationException.class, () -> compiler.compile(file, Optional.empty())); 116 117 assertThat(expected) 118 .hasMessageThat() 119 .isEqualTo("Descriptor for [compile_with_deps.proto] does not exist."); 120 } 121 122 @Test compileDevTuningfork()123 public void compileDevTuningfork() throws Exception { 124 File file = helper.getFile("dev_tuningfork.proto"); 125 126 FileDescriptor fDesc = compiler.compile(file, Optional.empty()); 127 128 Descriptor annotation = fDesc.findMessageTypeByName("Annotation"); 129 Descriptor fidelityParams = fDesc.findMessageTypeByName("FidelityParams"); 130 assertThat(annotation).isNotNull(); 131 assertThat(fidelityParams).isNotNull(); 132 } 133 134 @Test encodeAndDecode()135 public void encodeAndDecode() throws Exception { 136 String message = "com.google.tuningfork.FidelityParams"; 137 File protoFile = helper.getFile("dev_tuningfork.proto"); 138 File originalTextFile = helper.getFile("dev_tuningfork_fidelityparams_1.txt"); 139 Optional<File> errorFile = Optional.of(tempFolder.newFile("errors.txt")); 140 String root = tempFolder.getRoot().getAbsolutePath(); 141 File binaryFile = 142 compiler.encodeFromTextprotoFile( 143 message, 144 protoFile, 145 originalTextFile, 146 root + "/dev_tuningfork_fidelityparams_1.bin", 147 errorFile); 148 149 byte[] error = Files.toByteArray(errorFile.get()); 150 assertThat(error).isEqualTo(new byte[0]); 151 152 File decodedTextFile = 153 compiler.decodeToTextprotoFile( 154 message, 155 protoFile, 156 root + "/dev_tuningfork_fidelityparams_decoded.txt", 157 binaryFile, 158 errorFile); 159 160 String originalMessage = Files.asCharSource(originalTextFile, UTF_8).read(); 161 String decodedMessage = Files.asCharSource(decodedTextFile, UTF_8).read(); 162 error = Files.toByteArray(errorFile.get()); 163 assertThat(error).isEqualTo(new byte[0]); 164 assertThat(decodedMessage).isEqualTo(originalMessage); 165 } 166 167 @Test runEchoCommand()168 public void runEchoCommand() throws Exception { 169 String expected = "Hello world"; 170 ProcessBuilder builder = new ProcessBuilder(Arrays.asList("echo", expected)); 171 String result = new String(compiler.runCommand(builder), UTF_8); 172 assertThat(result).startsWith(expected); 173 } 174 } 175