1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34// 35// This test insures that google/protobuf/descriptor.pb.{h,cc} match exactly 36// what would be generated by the protocol compiler. These files are not 37// generated automatically at build time because they are compiled into the 38// protocol compiler itself. So, if they were auto-generated, you'd have a 39// chicken-and-egg problem. 40// 41// If this test fails, run the script 42// "generate_descriptor_proto.sh" and add 43// descriptor.pb.{h,cc} to your changelist. 44 45#include <map> 46 47#include <google/protobuf/compiler/cpp/cpp_generator.h> 48#include <google/protobuf/compiler/importer.h> 49#include <google/protobuf/descriptor.h> 50#include <google/protobuf/io/zero_copy_stream_impl.h> 51#include <google/protobuf/stubs/stl_util-inl.h> 52#include <google/protobuf/stubs/map-util.h> 53#include <google/protobuf/stubs/strutil.h> 54#include <google/protobuf/stubs/substitute.h> 55 56#include <google/protobuf/testing/file.h> 57#include <google/protobuf/testing/googletest.h> 58#include <gtest/gtest.h> 59 60namespace google { 61namespace protobuf { 62namespace compiler { 63namespace cpp { 64 65namespace { 66 67class MockErrorCollector : public MultiFileErrorCollector { 68 public: 69 MockErrorCollector() {} 70 ~MockErrorCollector() {} 71 72 string text_; 73 74 // implements ErrorCollector --------------------------------------- 75 void AddError(const string& filename, int line, int column, 76 const string& message) { 77 strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", 78 filename, line, column, message); 79 } 80}; 81 82class MockOutputDirectory : public OutputDirectory { 83 public: 84 MockOutputDirectory() {} 85 ~MockOutputDirectory() { 86 STLDeleteValues(&files_); 87 } 88 89 void ExpectFileMatches(const string& virtual_filename, 90 const string& physical_filename) { 91 string* expected_contents = FindPtrOrNull(files_, virtual_filename); 92 ASSERT_TRUE(expected_contents != NULL) 93 << "Generator failed to generate file: " << virtual_filename; 94 95 string actual_contents; 96 File::ReadFileToStringOrDie( 97 TestSourceDir() + "/" + physical_filename, 98 &actual_contents); 99 EXPECT_TRUE(actual_contents == *expected_contents) 100 << physical_filename << " needs to be regenerated. Please run " 101 "generate_descriptor_proto.sh and add this file " 102 "to your CL."; 103 } 104 105 // implements OutputDirectory -------------------------------------- 106 107 virtual io::ZeroCopyOutputStream* Open(const string& filename) { 108 string** map_slot = &files_[filename]; 109 if (*map_slot != NULL) delete *map_slot; 110 *map_slot = new string; 111 112 return new io::StringOutputStream(*map_slot); 113 } 114 115 private: 116 map<string, string*> files_; 117}; 118 119TEST(BootstrapTest, GeneratedDescriptorMatches) { 120 MockErrorCollector error_collector; 121 DiskSourceTree source_tree; 122 source_tree.MapPath("", TestSourceDir()); 123 Importer importer(&source_tree, &error_collector); 124 const FileDescriptor* proto_file = 125 importer.Import("google/protobuf/descriptor.proto"); 126 const FileDescriptor* plugin_proto_file = 127 importer.Import("google/protobuf/compiler/plugin.proto"); 128 EXPECT_EQ("", error_collector.text_); 129 ASSERT_TRUE(proto_file != NULL); 130 ASSERT_TRUE(plugin_proto_file != NULL); 131 132 CppGenerator generator; 133 MockOutputDirectory output_directory; 134 string error; 135 string parameter; 136 parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; 137 ASSERT_TRUE(generator.Generate(proto_file, parameter, 138 &output_directory, &error)); 139 parameter = "dllexport_decl=LIBPROTOC_EXPORT"; 140 ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter, 141 &output_directory, &error)); 142 143 output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h", 144 "google/protobuf/descriptor.pb.h"); 145 output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc", 146 "google/protobuf/descriptor.pb.cc"); 147 output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", 148 "google/protobuf/compiler/plugin.pb.h"); 149 output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", 150 "google/protobuf/compiler/plugin.pb.cc"); 151} 152 153} // namespace 154 155} // namespace cpp 156} // namespace compiler 157} // namespace protobuf 158} // namespace google 159