37 #include <sys/types.h>
53 #include <google/protobuf/unittest.pb.h>
75 using google::protobuf::io::win32::close;
76 using google::protobuf::io::win32::dup;
77 using google::protobuf::io::win32::dup2;
78 using google::protobuf::io::win32::open;
79 using google::protobuf::io::win32::write;
84 #if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
96 virtual void TearDown();
102 void RunWithArgs(std::vector<std::string>
args);
107 class NullCodeGenerator;
120 #ifdef PROTOBUF_OPENSOURCE
122 void SwitchToTempDirectory() {
125 #else // !PROTOBUF_OPENSOURCE
128 #endif // !PROTOBUF_OPENSOURCE
135 void ExpectNoErrors();
140 void ExpectErrorText(
const std::string& expected_text);
144 void ExpectErrorSubstring(
const std::string& expected_substring);
147 void ExpectCapturedStdout(
const std::string& expected_text);
151 void ExpectCapturedStdoutSubstringWithZeroReturnCode(
154 #if defined(_WIN32) && !defined(__CYGWIN__)
157 bool HasAlternateErrorSubstring(
const std::string& expected_substring);
158 #endif // _WIN32 && !__CYGWIN__
169 void ExpectGenerated(
const std::string& generator_name,
173 void ExpectGenerated(
const std::string& generator_name,
178 void ExpectGeneratedWithMultipleInputs(
const std::string& generator_name,
182 void ExpectGeneratedWithInsertions(
const std::string& generator_name,
191 void ExpectNullCodeGeneratorCalled(
const std::string& parameter);
195 void ReadDescriptorSet(
const std::string& filename,
198 void WriteDescriptorSet(
const std::string& filename,
201 void ExpectFileContent(
const std::string& filename,
232 class CommandLineInterfaceTest::NullCodeGenerator :
public CodeGenerator {
234 NullCodeGenerator() :
called_(
false) {}
235 ~NullCodeGenerator() {}
251 void CommandLineInterfaceTest::SetUp() {
264 CodeGenerator* generator =
new MockCodeGenerator(
"test_generator");
269 generator =
new MockCodeGenerator(
"alt_generator");
281 void CommandLineInterfaceTest::TearDown() {
295 RunWithArgs(
Split(command,
" ",
true));
298 void CommandLineInterfaceTest::RunWithArgs(std::vector<std::string>
args) {
302 #ifdef GOOGLE_PROTOBUF_TEST_PLUGIN_PATH
303 plugin_path = GOOGLE_PROTOBUF_TEST_PLUGIN_PATH;
305 const char* possible_paths[] = {
321 ".libs/test_plugin.exe",
326 if (
access(possible_paths[
i], F_OK) == 0) {
327 plugin_path = possible_paths[
i];
333 if (plugin_path.empty()) {
335 <<
"Plugin executable not found. Plugin tests are likely to fail.";
337 args.push_back(
"--plugin=prefix-gen-plug=" + plugin_path);
341 std::unique_ptr<const char*[]> argv(
new const char*[
args.size()]);
343 for (
int i = 0;
i <
args.size();
i++) {
345 argv[
i] =
args[
i].c_str();
351 #if !defined(__CYGWIN__)
359 #if !defined(__CYGWIN__)
369 std::string::size_type slash_pos =
name.find_last_of(
'/');
370 if (slash_pos != std::string::npos) {
385 void CommandLineInterfaceTest::CreateTempDir(
const std::string&
name) {
392 void CommandLineInterfaceTest::ExpectNoErrors() {
397 void CommandLineInterfaceTest::ExpectErrorText(
404 void CommandLineInterfaceTest::ExpectErrorSubstring(
410 #if defined(_WIN32) && !defined(__CYGWIN__)
411 bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
414 return error_text_.find(expected_substring) != std::string::npos;
416 #endif // _WIN32 && !__CYGWIN__
418 void CommandLineInterfaceTest::ExpectGenerated(
425 void CommandLineInterfaceTest::ExpectGenerated(
430 message_name, proto_name,
434 void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs(
438 message_name, all_proto_names,
442 void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
447 proto_name, message_name, proto_name,
451 void CommandLineInterfaceTest::CheckGeneratedAnnotations(
457 void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
465 void CommandLineInterfaceTest::ReadDescriptorSet(
471 if (!descriptor_set->ParseFromString(file_contents)) {
472 FAIL() <<
"Could not parse file contents: " <<
path;
476 void CommandLineInterfaceTest::WriteDescriptorSet(
479 GOOGLE_CHECK(descriptor_set->SerializeToString(&binary_proto));
480 CreateTempFile(filename, binary_proto);
483 void CommandLineInterfaceTest::ExpectCapturedStdout(
488 void CommandLineInterfaceTest::ExpectCapturedStdoutSubstringWithZeroReturnCode(
495 void CommandLineInterfaceTest::ExpectFileContent(
const std::string& filename,
507 TEST_F(CommandLineInterfaceTest, BasicOutput) {
510 CreateTempFile(
"foo.proto",
511 "syntax = \"proto2\";\n"
514 Run(
"protocol_compiler --test_out=$tmpdir "
515 "--proto_path=$tmpdir foo.proto");
518 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
521 TEST_F(CommandLineInterfaceTest, BasicOutput_DescriptorSetIn) {
525 file_descriptor_proto->
set_name(
"foo.proto");
528 WriteDescriptorSet(
"foo.bin", &file_descriptor_set);
530 Run(
"protocol_compiler --test_out=$tmpdir "
531 "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
534 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
537 TEST_F(CommandLineInterfaceTest, BasicPlugin) {
540 CreateTempFile(
"foo.proto",
541 "syntax = \"proto2\";\n"
544 Run(
"protocol_compiler --plug_out=$tmpdir "
545 "--proto_path=$tmpdir foo.proto");
548 ExpectGenerated(
"test_plugin",
"",
"foo.proto",
"Foo");
551 TEST_F(CommandLineInterfaceTest, BasicPlugin_DescriptorSetIn) {
556 file_descriptor_proto->
set_name(
"foo.proto");
559 WriteDescriptorSet(
"foo.bin", &file_descriptor_set);
561 Run(
"protocol_compiler --plug_out=$tmpdir "
562 "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
565 ExpectGenerated(
"test_plugin",
"",
"foo.proto",
"Foo");
568 TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
571 CreateTempFile(
"foo.proto",
572 "syntax = \"proto2\";\n"
575 Run(
"protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
576 "--proto_path=$tmpdir foo.proto");
579 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
580 ExpectGenerated(
"test_plugin",
"",
"foo.proto",
"Foo");
583 TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin_DescriptorSetIn) {
588 file_descriptor_proto->
set_name(
"foo.proto");
591 WriteDescriptorSet(
"foo.bin", &file_descriptor_set);
593 Run(
"protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
594 "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
597 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
598 ExpectGenerated(
"test_plugin",
"",
"foo.proto",
"Foo");
601 TEST_F(CommandLineInterfaceTest, MultipleInputs) {
604 CreateTempFile(
"foo.proto",
605 "syntax = \"proto2\";\n"
607 CreateTempFile(
"bar.proto",
608 "syntax = \"proto2\";\n"
611 Run(
"protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
612 "--proto_path=$tmpdir foo.proto bar.proto");
615 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
617 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
619 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
621 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
625 TEST_F(CommandLineInterfaceTest, MultipleInputs_DescriptorSetIn) {
630 file_descriptor_proto->
set_name(
"foo.proto");
633 file_descriptor_proto = file_descriptor_set.
add_file();
634 file_descriptor_proto->
set_name(
"bar.proto");
637 WriteDescriptorSet(
"foo.bin", &file_descriptor_set);
639 Run(
"protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
640 "--descriptor_set_in=$tmpdir/foo.bin foo.proto bar.proto");
643 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
645 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
647 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
649 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
653 TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) {
656 CreateTempFile(
"foo.proto",
657 "syntax = \"proto2\";\n"
659 CreateTempFile(
"bar.proto",
660 "syntax = \"proto2\";\n"
661 "import \"baz.proto\";\n"
663 " optional Baz a = 1;\n"
665 CreateTempFile(
"baz.proto",
666 "syntax = \"proto2\";\n"
669 Run(
"protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
670 "--proto_path=$tmpdir foo.proto bar.proto");
673 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
675 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
677 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
679 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
683 TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport_DescriptorSetIn) {
688 file_descriptor_proto->
set_name(
"foo.proto");
691 file_descriptor_proto = file_descriptor_set.
add_file();
692 file_descriptor_proto->
set_name(
"bar.proto");
697 field->set_type_name(
"Baz");
698 field->set_name(
"a");
699 field->set_number(1);
701 WriteDescriptorSet(
"foo_and_bar.bin", &file_descriptor_set);
704 file_descriptor_proto = file_descriptor_set.
add_file();
705 file_descriptor_proto->
set_name(
"baz.proto");
708 file_descriptor_proto = file_descriptor_set.
add_file();
709 file_descriptor_proto->
set_name(
"bat.proto");
714 field->set_type_name(
"Baz");
715 field->set_name(
"a");
716 field->set_number(1);
718 WriteDescriptorSet(
"baz_and_bat.bin", &file_descriptor_set);
720 "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
721 "--descriptor_set_in=$0 foo.proto bar.proto",
726 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
728 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
730 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
732 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
736 "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
737 "--descriptor_set_in=$0 baz.proto bat.proto",
742 ExpectGeneratedWithMultipleInputs(
"test_generator",
"baz.proto,bat.proto",
744 ExpectGeneratedWithMultipleInputs(
"test_generator",
"baz.proto,bat.proto",
746 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"baz.proto,bat.proto",
748 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"baz.proto,bat.proto",
752 TEST_F(CommandLineInterfaceTest,
753 MultipleInputsWithImport_DescriptorSetIn_DuplicateFileDescriptor) {
758 foo_file_descriptor_proto.
set_name(
"foo.proto");
761 file_descriptor_set.
add_file()->CopyFrom(foo_file_descriptor_proto);
764 file_descriptor_proto->
set_name(
"bar.proto");
770 field->set_type_name(
"Baz");
771 field->set_name(
"a");
772 field->set_number(1);
774 field->set_type_name(
"Foo");
775 field->set_name(
"f");
776 field->set_number(2);
777 WriteDescriptorSet(
"foo_and_bar.bin", &file_descriptor_set);
780 file_descriptor_set.
add_file()->CopyFrom(foo_file_descriptor_proto);
782 file_descriptor_proto = file_descriptor_set.
add_file();
783 file_descriptor_proto->
set_name(
"baz.proto");
788 field->set_type_name(
"Foo");
789 field->set_name(
"f");
790 field->set_number(1);
791 WriteDescriptorSet(
"foo_and_baz.bin", &file_descriptor_set);
794 "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
795 "--descriptor_set_in=$0 bar.proto",
800 ExpectGenerated(
"test_generator",
"",
"bar.proto",
"Bar");
801 ExpectGenerated(
"test_plugin",
"",
"bar.proto",
"Bar");
804 TEST_F(CommandLineInterfaceTest,
805 MultipleInputsWithImport_DescriptorSetIn_MissingImport) {
810 file_descriptor_proto->
set_name(
"foo.proto");
813 file_descriptor_proto = file_descriptor_set.
add_file();
814 file_descriptor_proto->
set_name(
"bar.proto");
819 field->set_type_name(
"Baz");
820 field->set_name(
"a");
821 field->set_number(1);
823 WriteDescriptorSet(
"foo_and_bar.bin", &file_descriptor_set);
826 file_descriptor_proto = file_descriptor_set.
add_file();
827 file_descriptor_proto->
set_name(
"baz.proto");
830 WriteDescriptorSet(
"baz.bin", &file_descriptor_set);
831 Run(
"protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
832 "--descriptor_set_in=$tmpdir/foo_and_bar.bin "
833 "foo.proto bar.proto");
834 ExpectErrorSubstring(
835 "bar.proto: Import \"baz.proto\" was not found or had errors.");
836 ExpectErrorSubstring(
"bar.proto: \"Baz\" is not defined.");
839 TEST_F(CommandLineInterfaceTest, CreateDirectory) {
842 CreateTempFile(
"bar/baz/foo.proto",
843 "syntax = \"proto2\";\n"
845 CreateTempDir(
"out");
846 CreateTempDir(
"plugout");
848 Run(
"protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout "
849 "--proto_path=$tmpdir bar/baz/foo.proto");
852 ExpectGenerated(
"test_generator",
"",
"bar/baz/foo.proto",
"Foo",
"out");
853 ExpectGenerated(
"test_plugin",
"",
"bar/baz/foo.proto",
"Foo",
"plugout");
856 TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
859 CreateTempFile(
"foo.proto",
860 "syntax = \"proto2\";\n"
863 Run(
"protocol_compiler --test_out=TestParameter:$tmpdir "
864 "--plug_out=TestPluginParameter:$tmpdir "
865 "--proto_path=$tmpdir foo.proto");
868 ExpectGenerated(
"test_generator",
"TestParameter",
"foo.proto",
"Foo");
869 ExpectGenerated(
"test_plugin",
"TestPluginParameter",
"foo.proto",
"Foo");
872 TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
876 CreateTempFile(
"foo.proto",
877 "syntax = \"proto2\";\n"
883 Run(
"protocol_compiler "
885 "--test_out=bar:$tmpdir/a "
887 "--test_out=baz:$tmpdir/b "
889 "--proto_path=$tmpdir foo.proto");
892 ExpectGenerated(
"test_generator",
"bar,foo1,foo2,foo3",
"foo.proto",
"Foo",
894 ExpectGenerated(
"test_generator",
"baz,foo1,foo2,foo3",
"foo.proto",
"Foo",
898 TEST_F(CommandLineInterfaceTest, ExtraPluginParameters) {
902 CreateTempFile(
"foo.proto",
903 "syntax = \"proto2\";\n"
909 Run(
"protocol_compiler "
911 "--plug_out=bar:$tmpdir/a "
913 "--plug_out=baz:$tmpdir/b "
915 "--proto_path=$tmpdir foo.proto");
918 ExpectGenerated(
"test_plugin",
"bar,foo1,foo2,foo3",
"foo.proto",
"Foo",
"a");
919 ExpectGenerated(
"test_plugin",
"baz,foo1,foo2,foo3",
"foo.proto",
"Foo",
"b");
922 TEST_F(CommandLineInterfaceTest, UnrecognizedExtraParameters) {
923 CreateTempFile(
"foo.proto",
924 "syntax = \"proto2\";\n"
927 Run(
"protocol_compiler --plug_out=TestParameter:$tmpdir "
928 "--unknown_plug_a_opt=Foo "
929 "--unknown_plug_b_opt=Bar "
930 "--proto_path=$tmpdir foo.proto");
932 ExpectErrorSubstring(
"Unknown flag: --unknown_plug_a_opt");
933 ExpectErrorSubstring(
"Unknown flag: --unknown_plug_b_opt");
936 TEST_F(CommandLineInterfaceTest, ExtraPluginParametersForOutParameters) {
947 CreateTempFile(
"foo.proto",
948 "syntax = \"proto2\";\n"
951 Run(
"protocol_compiler --plug_out=TestParameter:$tmpdir "
952 "--xyz_opt=foo=bar --xyz_out=$tmpdir "
953 "--abc_out=$tmpdir --abc_opt=foo=bar "
954 "--unknown_plug_opt=Foo "
955 "--proto_path=$tmpdir foo.proto");
957 ExpectErrorText(
"Unknown flag: --unknown_plug_opt\n");
963 CreateTempFile(
"foo.proto",
964 "syntax = \"proto2\";\n"
967 Run(
"protocol_compiler "
968 "--test_out=TestParameter:$tmpdir "
969 "--plug_out=TestPluginParameter:$tmpdir "
970 "--test_out=insert=test_generator,test_plugin:$tmpdir "
971 "--plug_out=insert=test_generator,test_plugin:$tmpdir "
972 "--proto_path=$tmpdir foo.proto");
975 ExpectGeneratedWithInsertions(
"test_generator",
"TestParameter",
976 "test_generator,test_plugin",
"foo.proto",
978 ExpectGeneratedWithInsertions(
"test_plugin",
"TestPluginParameter",
979 "test_generator,test_plugin",
"foo.proto",
983 TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) {
986 CreateTempFile(
"foo.proto",
987 "syntax = \"proto2\";\n"
988 "message MockCodeGenerator_Annotate {}\n");
990 Run(
"protocol_compiler "
991 "--test_out=TestParameter:$tmpdir "
992 "--plug_out=TestPluginParameter:$tmpdir "
993 "--test_out=insert=test_generator,test_plugin:$tmpdir "
994 "--plug_out=insert=test_generator,test_plugin:$tmpdir "
995 "--proto_path=$tmpdir foo.proto");
998 CheckGeneratedAnnotations(
"test_generator",
"foo.proto");
999 CheckGeneratedAnnotations(
"test_plugin",
"foo.proto");
1004 TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
1007 CreateTempFile(
"foo.proto",
"syntax = \"proto2\";\n");
1009 Run(
"protocol_compiler --null_out=C:\\ "
1010 "--proto_path=$tmpdir foo.proto");
1013 ExpectNullCodeGeneratorCalled(
"");
1016 TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) {
1019 CreateTempFile(
"foo.proto",
"syntax = \"proto2\";\n");
1021 Run(
"protocol_compiler --null_out=bar:C:\\ "
1022 "--proto_path=$tmpdir foo.proto");
1025 ExpectNullCodeGeneratorCalled(
"bar");
1028 TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
1032 CreateTempFile(
"foo.proto",
1033 "syntax = \"proto2\";\n"
1034 "message Foo {}\n");
1036 Run(
"protocol_compiler --test_out=$tmpdir\\ "
1037 "--proto_path=$tmpdir\\ foo.proto");
1040 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
1043 TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) {
1044 EXPECT_EQ(
"The system cannot find the file specified.\r\n",
1045 Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
1048 #endif // defined(_WIN32) || defined(__CYGWIN__)
1050 TEST_F(CommandLineInterfaceTest, PathLookup) {
1053 CreateTempFile(
"b/bar.proto",
1054 "syntax = \"proto2\";\n"
1055 "message Bar {}\n");
1056 CreateTempFile(
"a/foo.proto",
1057 "syntax = \"proto2\";\n"
1058 "import \"bar.proto\";\n"
1060 " optional Bar a = 1;\n"
1062 CreateTempFile(
"b/foo.proto",
"this should not be parsed\n");
1064 Run(
"protocol_compiler --test_out=$tmpdir "
1065 "--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto");
1068 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
1071 TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
1074 CreateTempFile(
"b/bar.proto",
1075 "syntax = \"proto2\";\n"
1076 "message Bar {}\n");
1077 CreateTempFile(
"a/foo.proto",
1078 "syntax = \"proto2\";\n"
1079 "import \"bar.proto\";\n"
1081 " optional Bar a = 1;\n"
1083 CreateTempFile(
"b/foo.proto",
"this should not be parsed\n");
1086 "protocol_compiler --test_out=$$tmpdir --proto_path=$0 foo.proto",
1091 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
1094 TEST_F(CommandLineInterfaceTest, NonRootMapping) {
1097 CreateTempFile(
"foo.proto",
1098 "syntax = \"proto2\";\n"
1099 "message Foo {}\n");
1101 Run(
"protocol_compiler --test_out=$tmpdir "
1102 "--proto_path=bar=$tmpdir bar/foo.proto");
1105 ExpectGenerated(
"test_generator",
"",
"bar/foo.proto",
"Foo");
1108 TEST_F(CommandLineInterfaceTest, PathWithEqualsSign) {
1111 CreateTempDir(
"with=sign");
1112 CreateTempFile(
"with=sign/foo.proto",
1113 "syntax = \"proto2\";\n"
1114 "message Foo {}\n");
1116 Run(
"protocol_compiler --test_out=$tmpdir "
1117 "--proto_path=$tmpdir/with=sign foo.proto");
1120 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
1123 TEST_F(CommandLineInterfaceTest, MultipleGenerators) {
1127 CreateTempFile(
"foo.proto",
1128 "syntax = \"proto2\";\n"
1129 "message Foo {}\n");
1134 Run(
"protocol_compiler "
1135 "--test_out=$tmpdir/a "
1136 "--alt_out=$tmpdir/b "
1137 "--proto_path=$tmpdir foo.proto");
1140 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo",
"a");
1141 ExpectGenerated(
"alt_generator",
"",
"foo.proto",
"Foo",
"b");
1144 TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
1148 CreateTempFile(
"foo.proto",
1149 "syntax = \"proto2\";\n"
1150 "message Foo {}\n");
1152 Run(
"protocol_compiler --disallow_services --test_out=$tmpdir "
1153 "--proto_path=$tmpdir foo.proto");
1156 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
1159 TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
1162 CreateTempFile(
"foo.proto",
1163 "syntax = \"proto2\";\n"
1165 "service Bar {}\n");
1167 Run(
"protocol_compiler --disallow_services --test_out=$tmpdir "
1168 "--proto_path=$tmpdir foo.proto");
1170 ExpectErrorSubstring(
"foo.proto: This file contains services");
1173 TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
1176 CreateTempFile(
"foo.proto",
1177 "syntax = \"proto2\";\n"
1179 "service Bar {}\n");
1181 Run(
"protocol_compiler --test_out=$tmpdir "
1182 "--proto_path=$tmpdir foo.proto");
1185 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
1188 TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) {
1189 CreateTempFile(
"foo.proto",
1190 "syntax = \"proto2\";\n"
1191 "import \"bar.proto\";\n"
1192 "message Foo { optional Bar bar = 1; }");
1193 CreateTempFile(
"bar.proto",
1194 "syntax = \"proto2\";\n"
1195 "message Bar { optional string text = 1; }");
1197 Run(
"protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
1198 "--direct_dependencies= foo.proto");
1201 "foo.proto: File is imported but not declared in --direct_dependencies: "
1205 TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing) {
1206 CreateTempFile(
"foo.proto",
1207 "syntax = \"proto2\";\n"
1208 "import \"bar.proto\";\n"
1209 "import \"bla.proto\";\n"
1210 "message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
1211 CreateTempFile(
"bar.proto",
1212 "syntax = \"proto2\";\n"
1213 "message Bar { optional string text = 1; }");
1214 CreateTempFile(
"bla.proto",
1215 "syntax = \"proto2\";\n"
1216 "message Bla { optional int64 number = 1; }");
1218 Run(
"protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
1219 "--direct_dependencies=bla.proto foo.proto");
1222 "foo.proto: File is imported but not declared in --direct_dependencies: "
1226 TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation) {
1227 CreateTempFile(
"foo.proto",
1228 "syntax = \"proto2\";\n"
1229 "import \"bar.proto\";\n"
1230 "message Foo { optional Bar bar = 1; }");
1231 CreateTempFile(
"bar.proto",
1232 "syntax = \"proto2\";\n"
1233 "message Bar { optional string text = 1; }");
1235 Run(
"protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
1236 "--direct_dependencies=bar.proto foo.proto");
1241 TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation_MultiImports) {
1242 CreateTempFile(
"foo.proto",
1243 "syntax = \"proto2\";\n"
1244 "import \"bar.proto\";\n"
1245 "import \"bla.proto\";\n"
1246 "message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
1247 CreateTempFile(
"bar.proto",
1248 "syntax = \"proto2\";\n"
1249 "message Bar { optional string text = 1; }");
1250 CreateTempFile(
"bla.proto",
1251 "syntax = \"proto2\";\n"
1252 "message Bla { optional int64 number = 1; }");
1254 Run(
"protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
1255 "--direct_dependencies=bar.proto:bla.proto foo.proto");
1260 TEST_F(CommandLineInterfaceTest, DirectDependencies_ProvidedMultipleTimes) {
1261 CreateTempFile(
"foo.proto",
"syntax = \"proto2\";\n");
1263 Run(
"protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
1264 "--direct_dependencies=bar.proto --direct_dependencies=bla.proto "
1268 "--direct_dependencies may only be passed once. To specify multiple "
1269 "direct dependencies, pass them all as a single parameter separated by "
1273 TEST_F(CommandLineInterfaceTest, DirectDependencies_CustomErrorMessage) {
1274 CreateTempFile(
"foo.proto",
1275 "syntax = \"proto2\";\n"
1276 "import \"bar.proto\";\n"
1277 "message Foo { optional Bar bar = 1; }");
1278 CreateTempFile(
"bar.proto",
1279 "syntax = \"proto2\";\n"
1280 "message Bar { optional string text = 1; }");
1282 std::vector<std::string> commands;
1283 commands.push_back(
"protocol_compiler");
1284 commands.push_back(
"--test_out=$tmpdir");
1285 commands.push_back(
"--proto_path=$tmpdir");
1286 commands.push_back(
"--direct_dependencies=");
1287 commands.push_back(
"--direct_dependencies_violation_msg=Bla \"%s\" Bla");
1288 commands.push_back(
"foo.proto");
1289 RunWithArgs(commands);
1291 ExpectErrorText(
"foo.proto: Bla \"bar.proto\" Bla\n");
1294 TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
1297 CreateTempFile(
"foo.proto",
1298 "syntax = \"proto2\";\n"
1299 "message Foo {}\n");
1301 Run(
"protocol_compiler --test_out=$tmpdir "
1302 "--proto_path=$tmpdir $tmpdir/foo.proto");
1305 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
1308 TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
1309 CreateTempFile(
"foo.proto",
1310 "syntax = \"proto2\";\n"
1311 "message Foo {}\n");
1312 CreateTempFile(
"bar.proto",
1313 "syntax = \"proto2\";\n"
1314 "import \"foo.proto\";\n"
1316 " optional Foo foo = 1;\n"
1319 Run(
"protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
1320 "--proto_path=$tmpdir bar.proto");
1325 ReadDescriptorSet(
"descriptor_set", &descriptor_set);
1326 if (HasFatalFailure())
return;
1332 EXPECT_EQ(
"Bar", descriptor_set.
file(0).message_type(0).name());
1333 EXPECT_EQ(
"foo", descriptor_set.
file(0).message_type(0).field(0).name());
1334 EXPECT_TRUE(descriptor_set.
file(0).message_type(0).field(0).has_json_name());
1337 TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) {
1338 CreateTempFile(
"foo.proto",
1339 "syntax = \"proto2\";\n"
1340 "message Foo {}\n");
1341 CreateTempFile(
"bar.proto",
1342 "syntax = \"proto2\";\n"
1343 "import \"foo.proto\";\n"
1345 " optional Foo foo = 1;\n"
1347 CreateTempFile(
"baz.proto",
1348 "syntax = \"proto2\";\n"
1349 "import \"foo.proto\";\n"
1351 " optional Foo foo = 1;\n"
1354 Run(
"protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
1355 "--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto");
1360 ReadDescriptorSet(
"descriptor_set", &descriptor_set);
1361 if (HasFatalFailure())
return;
1371 EXPECT_EQ(
"Bar", descriptor_set.
file(1).message_type(0).name());
1372 EXPECT_EQ(
"foo", descriptor_set.
file(1).message_type(0).field(0).name());
1373 EXPECT_TRUE(descriptor_set.
file(1).message_type(0).field(0).has_json_name());
1376 TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
1377 CreateTempFile(
"foo.proto",
1378 "syntax = \"proto2\";\n"
1379 "message Foo {}\n");
1380 CreateTempFile(
"bar.proto",
1381 "syntax = \"proto2\";\n"
1382 "import \"foo.proto\";\n"
1384 " optional Foo foo = 1;\n"
1387 Run(
"protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
1388 "--include_source_info --proto_path=$tmpdir bar.proto");
1393 ReadDescriptorSet(
"descriptor_set", &descriptor_set);
1394 if (HasFatalFailure())
return;
1401 TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
1402 CreateTempFile(
"foo.proto",
1403 "syntax = \"proto2\";\n"
1404 "message Foo {}\n");
1405 CreateTempFile(
"bar.proto",
1406 "syntax = \"proto2\";\n"
1407 "import \"foo.proto\";\n"
1409 " optional Foo foo = 1;\n"
1412 Run(
"protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
1413 "--include_imports --proto_path=$tmpdir bar.proto");
1418 ReadDescriptorSet(
"descriptor_set", &descriptor_set);
1419 if (HasFatalFailure())
return;
1421 if (descriptor_set.
file(0).name() ==
"bar.proto") {
1432 TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
1433 CreateTempFile(
"foo.proto",
1434 "syntax = \"proto2\";\n"
1435 "message Foo {}\n");
1436 CreateTempFile(
"bar.proto",
1437 "syntax = \"proto2\";\n"
1438 "import \"foo.proto\";\n"
1440 " optional Foo foo = 1;\n"
1443 Run(
"protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
1444 "--include_imports --include_source_info --proto_path=$tmpdir bar.proto");
1449 ReadDescriptorSet(
"descriptor_set", &descriptor_set);
1450 if (HasFatalFailure())
return;
1452 if (descriptor_set.
file(0).name() ==
"bar.proto") {
1466 TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) {
1467 CreateTempFile(
"foo.proto",
1468 "syntax = \"proto2\";\n"
1469 "message Foo {}\n");
1470 CreateTempFile(
"bar.proto",
1471 "syntax = \"proto2\";\n"
1472 "import \"foo.proto\";\n"
1474 " optional Foo foo = 1;\n"
1477 Run(
"protocol_compiler --dependency_out=$tmpdir/manifest "
1478 "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto");
1481 "Can only process one input file when using --dependency_out=FILE.\n");
1484 #ifdef PROTOBUF_OPENSOURCE
1485 TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) {
1486 CreateTempFile(
"foo.proto",
1487 "syntax = \"proto2\";\n"
1488 "message Foo {}\n");
1489 CreateTempFile(
"bar.proto",
1490 "syntax = \"proto2\";\n"
1491 "import \"foo.proto\";\n"
1493 " optional Foo foo = 1;\n"
1497 SwitchToTempDirectory();
1499 Run(
"protocol_compiler --dependency_out=manifest --test_out=. "
1504 ExpectFileContent(
"manifest",
1505 "bar.proto.MockCodeGenerator.test_generator: "
1506 "foo.proto\\\n bar.proto");
1510 #else // !PROTOBUF_OPENSOURCE
1513 #endif // !PROTOBUF_OPENSOURCE
1515 TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) {
1516 CreateTempFile(
"foo.proto",
1517 "syntax = \"proto2\";\n"
1518 "message Foo {}\n");
1519 CreateTempFile(
"bar.proto",
1520 "syntax = \"proto2\";\n"
1521 "import \"foo.proto\";\n"
1523 " optional Foo foo = 1;\n"
1526 Run(
"protocol_compiler --dependency_out=$tmpdir/manifest "
1527 "--test_out=$tmpdir --proto_path=$tmpdir bar.proto");
1531 ExpectFileContent(
"manifest",
1532 "$tmpdir/bar.proto.MockCodeGenerator.test_generator: "
1533 "$tmpdir/foo.proto\\\n $tmpdir/bar.proto");
1537 TEST_F(CommandLineInterfaceTest, TestArgumentFile) {
1540 CreateTempFile(
"foo.proto",
1541 "syntax = \"proto2\";\n"
1542 "message Foo {}\n");
1543 CreateTempFile(
"bar.proto",
1544 "syntax = \"proto2\";\n"
1545 "message Bar {}\n");
1546 CreateTempFile(
"arguments.txt",
1547 "--test_out=$tmpdir\n"
1548 "--plug_out=$tmpdir\n"
1549 "--proto_path=$tmpdir\n"
1550 "--direct_dependencies_violation_msg=%s is not imported\n"
1554 Run(
"protocol_compiler @$tmpdir/arguments.txt");
1557 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
1558 "foo.proto",
"Foo");
1559 ExpectGeneratedWithMultipleInputs(
"test_generator",
"foo.proto,bar.proto",
1560 "bar.proto",
"Bar");
1561 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
1562 "foo.proto",
"Foo");
1563 ExpectGeneratedWithMultipleInputs(
"test_plugin",
"foo.proto,bar.proto",
1564 "bar.proto",
"Bar");
1570 TEST_F(CommandLineInterfaceTest, ParseErrors) {
1573 CreateTempFile(
"foo.proto",
1574 "syntax = \"proto2\";\n"
1577 Run(
"protocol_compiler --test_out=$tmpdir "
1578 "--proto_path=$tmpdir foo.proto");
1581 "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
1584 TEST_F(CommandLineInterfaceTest, ParseErrors_DescriptorSetIn) {
1586 CreateTempFile(
"foo.bin",
"not a FileDescriptorSet");
1588 Run(
"protocol_compiler --test_out=$tmpdir "
1589 "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
1591 ExpectErrorText(
"$tmpdir/foo.bin: Unable to parse.\n");
1594 TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
1600 CreateTempFile(
"bar.proto",
1601 "syntax = \"proto2\";\n"
1603 CreateTempFile(
"baz.proto",
1604 "syntax = \"proto2\";\n"
1605 "import \"bar.proto\";\n");
1606 CreateTempFile(
"foo.proto",
1607 "syntax = \"proto2\";\n"
1608 "import \"bar.proto\";\n"
1609 "import \"baz.proto\";\n");
1611 Run(
"protocol_compiler --test_out=$tmpdir "
1612 "--proto_path=$tmpdir foo.proto");
1615 "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n"
1616 "baz.proto:2:1: Import \"bar.proto\" was not found or had errors.\n"
1617 "foo.proto:2:1: Import \"bar.proto\" was not found or had errors.\n"
1618 "foo.proto:3:1: Import \"baz.proto\" was not found or had errors.\n");
1621 TEST_F(CommandLineInterfaceTest, RecursiveImportFails) {
1623 CreateTempFile(
"foo.proto",
1624 "syntax = \"proto2\";\n"
1625 "import \"foo.proto\";\n");
1627 Run(
"protocol_compiler --test_out=$tmpdir "
1628 "--proto_path=$tmpdir foo.proto");
1630 ExpectErrorSubstring(
1631 "foo.proto:2:1: File recursively imports itself: "
1632 "foo.proto -> foo.proto\n");
1635 TEST_F(CommandLineInterfaceTest, InputNotFoundError) {
1638 Run(
"protocol_compiler --test_out=$tmpdir "
1639 "--proto_path=$tmpdir foo.proto");
1641 ExpectErrorText(
"foo.proto: No such file or directory\n");
1644 TEST_F(CommandLineInterfaceTest, InputNotFoundError_DescriptorSetIn) {
1647 Run(
"protocol_compiler --test_out=$tmpdir "
1648 "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
1650 ExpectErrorText(
"$tmpdir/foo.bin: No such file or directory\n");
1653 TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
1657 Run(
"protocol_compiler --test_out=$tmpdir "
1658 "--proto_path=$tmpdir $tmpdir/foo.proto");
1660 ExpectErrorText(
"$tmpdir/foo.proto: No such file or directory\n");
1663 TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) {
1667 CreateTempFile(
"foo.proto",
1668 "syntax = \"proto2\";\n"
1669 "message Foo {}\n");
1672 CreateTempFile(
"bar/dummy",
"");
1674 Run(
"protocol_compiler --test_out=$tmpdir "
1675 "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
1678 "$tmpdir/foo.proto: File does not reside within any path "
1679 "specified using --proto_path (or -I). You must specify a "
1680 "--proto_path which encompasses this file. Note that the "
1681 "proto_path must be an exact prefix of the .proto file "
1682 "names -- protoc is too dumb to figure out when two paths "
1683 "(e.g. absolute and relative) are equivalent (it's harder "
1684 "than you think).\n");
1687 TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) {
1692 CreateTempFile(
"bar/dummy",
"");
1694 Run(
"protocol_compiler --test_out=$tmpdir "
1695 "--proto_path=$tmpdir/bar $tmpdir/foo.proto");
1697 ExpectErrorText(
"$tmpdir/foo.proto: No such file or directory\n");
1700 TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
1704 CreateTempFile(
"foo/foo.proto",
1705 "syntax = \"proto2\";\n"
1706 "message Foo {}\n");
1707 CreateTempFile(
"bar/foo.proto",
1708 "syntax = \"proto2\";\n"
1709 "message Bar {}\n");
1711 Run(
"protocol_compiler --test_out=$tmpdir "
1712 "--proto_path=$tmpdir/foo --proto_path=$tmpdir/bar "
1713 "$tmpdir/bar/foo.proto");
1716 "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path "
1717 "by \"$tmpdir/foo/foo.proto\". Either use the latter "
1718 "file as your input or reorder the --proto_path so that the "
1719 "former file's location comes first.\n");
1722 TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
1725 Run(
"protocol_compiler --test_out=$tmpdir "
1726 "--proto_path=$tmpdir/foo foo.proto");
1729 "$tmpdir/foo: warning: directory does not exist.\n"
1730 "foo.proto: No such file or directory\n");
1733 TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn) {
1734 Run(
"protocol_compiler --test_out=$tmpdir "
1735 "--proto_path=$tmpdir --descriptor_set_in=$tmpdir/foo.bin foo.proto");
1736 ExpectErrorText(
"$tmpdir/foo.bin: No such file or directory\n");
1738 Run(
"protocol_compiler --test_out=$tmpdir "
1739 "--descriptor_set_in=$tmpdir/foo.bin --proto_path=$tmpdir foo.proto");
1740 ExpectErrorText(
"$tmpdir/foo.bin: No such file or directory\n");
1743 TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn_CompileFiles) {
1752 file_descriptor_proto->
set_name(
"foo.proto");
1755 WriteDescriptorSet(
"foo.bin", &file_descriptor_set);
1757 CreateTempFile(
"foo.proto",
1758 "syntax = \"proto2\";\n"
1759 "message FooBar { required string foo_message = 1; }\n");
1761 Run(
"protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
1762 "--descriptor_set_in=$tmpdir/foo.bin "
1763 "--include_source_info "
1764 "--proto_path=$tmpdir foo.proto");
1769 ReadDescriptorSet(
"descriptor_set", &descriptor_set);
1776 EXPECT_EQ(
"FooBar", descriptor_set.
file(0).message_type(0).name());
1778 descriptor_set.
file(0).message_type(0).field(0).name());
1781 TEST_F(CommandLineInterfaceTest, ProtoPathAndDependencyOut) {
1782 Run(
"protocol_compiler --test_out=$tmpdir "
1783 "--dependency_out=$tmpdir/manifest "
1784 "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
1786 "--descriptor_set_in cannot be used with --dependency_out.\n");
1788 Run(
"protocol_compiler --test_out=$tmpdir "
1789 "--descriptor_set_in=$tmpdir/foo.bin "
1790 "--dependency_out=$tmpdir/manifest foo.proto");
1792 "--dependency_out cannot be used with --descriptor_set_in.\n");
1795 TEST_F(CommandLineInterfaceTest, MissingInputError) {
1798 Run(
"protocol_compiler --test_out=$tmpdir "
1799 "--proto_path=$tmpdir");
1801 ExpectErrorText(
"Missing input file.\n");
1804 TEST_F(CommandLineInterfaceTest, MissingOutputError) {
1805 CreateTempFile(
"foo.proto",
1806 "syntax = \"proto2\";\n"
1807 "message Foo {}\n");
1809 Run(
"protocol_compiler --proto_path=$tmpdir foo.proto");
1811 ExpectErrorText(
"Missing output directives.\n");
1814 TEST_F(CommandLineInterfaceTest, OutputWriteError) {
1815 CreateTempFile(
"foo.proto",
1816 "syntax = \"proto2\";\n"
1817 "message Foo {}\n");
1823 CreateTempDir(output_file);
1825 Run(
"protocol_compiler --test_out=$tmpdir "
1826 "--proto_path=$tmpdir foo.proto");
1833 #if defined(_WIN32) && !defined(__CYGWIN__)
1835 if (HasAlternateErrorSubstring(output_file +
": Permission denied")) {
1840 ExpectErrorSubstring(output_file +
": Is a directory");
1843 TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) {
1844 CreateTempFile(
"foo.proto",
1845 "syntax = \"proto2\";\n"
1846 "message Foo {}\n");
1852 CreateTempDir(output_file);
1854 Run(
"protocol_compiler --plug_out=$tmpdir "
1855 "--proto_path=$tmpdir foo.proto");
1857 #if defined(_WIN32) && !defined(__CYGWIN__)
1859 if (HasAlternateErrorSubstring(output_file +
": Permission denied")) {
1864 ExpectErrorSubstring(output_file +
": Is a directory");
1867 TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
1868 CreateTempFile(
"foo.proto",
1869 "syntax = \"proto2\";\n"
1870 "message Foo {}\n");
1872 Run(
"protocol_compiler --test_out=$tmpdir/nosuchdir "
1873 "--proto_path=$tmpdir foo.proto");
1875 ExpectErrorSubstring(
"nosuchdir/: No such file or directory");
1878 TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) {
1879 CreateTempFile(
"foo.proto",
1880 "syntax = \"proto2\";\n"
1881 "message Foo {}\n");
1883 Run(
"protocol_compiler --plug_out=$tmpdir/nosuchdir "
1884 "--proto_path=$tmpdir foo.proto");
1886 ExpectErrorSubstring(
"nosuchdir/: No such file or directory");
1889 TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
1890 CreateTempFile(
"foo.proto",
1891 "syntax = \"proto2\";\n"
1892 "message Foo {}\n");
1894 Run(
"protocol_compiler --test_out=$tmpdir/foo.proto "
1895 "--proto_path=$tmpdir foo.proto");
1897 #if defined(_WIN32) && !defined(__CYGWIN__)
1899 if (HasAlternateErrorSubstring(
"foo.proto/: Invalid argument")) {
1904 ExpectErrorSubstring(
"foo.proto/: Not a directory");
1907 TEST_F(CommandLineInterfaceTest, GeneratorError) {
1908 CreateTempFile(
"foo.proto",
1909 "syntax = \"proto2\";\n"
1910 "message MockCodeGenerator_Error {}\n");
1912 Run(
"protocol_compiler --test_out=$tmpdir "
1913 "--proto_path=$tmpdir foo.proto");
1915 ExpectErrorSubstring(
1916 "--test_out: foo.proto: Saw message type MockCodeGenerator_Error.");
1919 TEST_F(CommandLineInterfaceTest, GeneratorPluginError) {
1922 CreateTempFile(
"foo.proto",
1923 "syntax = \"proto2\";\n"
1924 "message MockCodeGenerator_Error {}\n");
1926 Run(
"protocol_compiler --plug_out=TestParameter:$tmpdir "
1927 "--proto_path=$tmpdir foo.proto");
1929 ExpectErrorSubstring(
1930 "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error.");
1933 TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) {
1936 CreateTempFile(
"foo.proto",
1937 "syntax = \"proto2\";\n"
1938 "message MockCodeGenerator_Exit {}\n");
1940 Run(
"protocol_compiler --plug_out=TestParameter:$tmpdir "
1941 "--proto_path=$tmpdir foo.proto");
1943 ExpectErrorSubstring(
"Saw message type MockCodeGenerator_Exit.");
1944 ExpectErrorSubstring(
1945 "--plug_out: prefix-gen-plug: Plugin failed with status code 123.");
1948 TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) {
1951 CreateTempFile(
"foo.proto",
1952 "syntax = \"proto2\";\n"
1953 "message MockCodeGenerator_Abort {}\n");
1955 Run(
"protocol_compiler --plug_out=TestParameter:$tmpdir "
1956 "--proto_path=$tmpdir foo.proto");
1958 ExpectErrorSubstring(
"Saw message type MockCodeGenerator_Abort.");
1963 ExpectErrorSubstring(
1964 "--plug_out: prefix-gen-plug: Plugin failed with status code");
1967 ExpectErrorSubstring(
"--plug_out: prefix-gen-plug: Plugin killed by signal");
1971 TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) {
1972 CreateTempFile(
"foo.proto",
1973 "syntax = \"proto2\";\n"
1974 "message MockCodeGenerator_HasSourceCodeInfo {}\n");
1976 Run(
"protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
1978 ExpectErrorSubstring(
1979 "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1.");
1982 TEST_F(CommandLineInterfaceTest, PluginReceivesJsonName) {
1983 CreateTempFile(
"foo.proto",
1984 "syntax = \"proto2\";\n"
1985 "message MockCodeGenerator_HasJsonName {\n"
1986 " optional int32 value = 1;\n"
1989 Run(
"protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
1991 ExpectErrorSubstring(
"Saw json_name: 1");
1994 TEST_F(CommandLineInterfaceTest, PluginReceivesCompilerVersion) {
1995 CreateTempFile(
"foo.proto",
1996 "syntax = \"proto2\";\n"
1997 "message MockCodeGenerator_ShowVersionNumber {\n"
1998 " optional int32 value = 1;\n"
2001 Run(
"protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
2003 ExpectErrorSubstring(
StringPrintf(
"Saw compiler_version: %d %s",
2008 TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
2011 CreateTempFile(
"error.proto",
2012 "syntax = \"proto2\";\n"
2013 "message Foo {}\n");
2015 Run(
"protocol_compiler --badplug_out=TestParameter:$tmpdir "
2016 "--plugin=prefix-gen-badplug=no_such_file "
2017 "--proto_path=$tmpdir error.proto");
2020 ExpectErrorSubstring(
"--badplug_out: prefix-gen-badplug: " +
2021 Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
2024 ExpectErrorSubstring(
"no_such_file: program not found or is not executable");
2026 ExpectErrorSubstring(
2027 "Please specify a program using absolute path or make sure "
2028 "the program is available in your PATH system variable");
2031 ExpectErrorSubstring(
2032 "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1.");
2036 TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
2039 CreateTempFile(
"error.proto",
2040 "syntax = \"proto2\";\n"
2041 "message Foo {}\n");
2044 Run(
"protocol_compiler --plug_out=TestParameter:$tmpdir "
2045 "--proto_path=$tmpdir error.proto");
2047 ExpectErrorSubstring(
"Unknown flag: --plug_out");
2050 TEST_F(CommandLineInterfaceTest, HelpText) {
2051 Run(
"test_exec_name --help");
2053 ExpectCapturedStdoutSubstringWithZeroReturnCode(
"Usage: test_exec_name ");
2054 ExpectCapturedStdoutSubstringWithZeroReturnCode(
"--test_out=OUT_DIR");
2055 ExpectCapturedStdoutSubstringWithZeroReturnCode(
"Test output.");
2056 ExpectCapturedStdoutSubstringWithZeroReturnCode(
"--alt_out=OUT_DIR");
2057 ExpectCapturedStdoutSubstringWithZeroReturnCode(
"Alt output.");
2060 TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
2064 CreateTempFile(
"foo.proto",
2065 "syntax = \"proto2\";\n"
2068 Run(
"protocol_compiler --test_out=$tmpdir "
2069 "--proto_path=$tmpdir --error_format=gcc foo.proto");
2072 "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
2075 TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
2078 CreateTempFile(
"foo.proto",
2079 "syntax = \"proto2\";\n"
2082 Run(
"protocol_compiler --test_out=$tmpdir "
2083 "--proto_path=$tmpdir --error_format=msvs foo.proto");
2086 "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement "
2087 "(e.g. \"message\").\n");
2090 TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
2093 CreateTempFile(
"foo.proto",
2094 "syntax = \"proto2\";\n"
2097 Run(
"protocol_compiler --test_out=$tmpdir "
2098 "--proto_path=$tmpdir --error_format=invalid foo.proto");
2100 ExpectErrorText(
"Unknown error format: invalid\n");
2106 TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
2109 CreateTempFile(
"foo.proto",
2110 "syntax = \"proto2\";\n"
2111 "message Foo {}\n");
2113 Run(
"protocol_compiler -t$tmpdir "
2114 "--proto_path=$tmpdir foo.proto");
2117 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
2120 TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
2123 CreateTempFile(
"foo.proto",
2124 "syntax = \"proto2\";\n"
2125 "message Foo {}\n");
2127 Run(
"protocol_compiler --test_out $tmpdir "
2128 "--proto_path=$tmpdir foo.proto");
2131 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
2134 TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
2138 CreateTempFile(
"foo.proto",
2139 "syntax = \"proto2\";\n"
2140 "message Foo {}\n");
2142 Run(
"protocol_compiler -t $tmpdir "
2143 "--proto_path=$tmpdir foo.proto");
2146 ExpectGenerated(
"test_generator",
"",
"foo.proto",
"Foo");
2149 TEST_F(CommandLineInterfaceTest, MissingValueError) {
2152 Run(
"protocol_compiler --test_out --proto_path=$tmpdir foo.proto");
2154 ExpectErrorText(
"Missing value for flag: --test_out\n");
2157 TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
2161 Run(
"protocol_compiler --test_out");
2163 ExpectErrorText(
"Missing value for flag: --test_out\n");
2166 TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) {
2167 CreateTempFile(
"foo.proto",
2168 "syntax = \"proto2\";\n"
2171 " optional int32 a = 2;\n"
2172 " optional string b = 4;\n"
2173 " optional string c = 5;\n"
2174 " optional int64 d = 8;\n"
2175 " optional double e = 10;\n"
2177 CreateTempFile(
"bar.proto",
2178 "syntax = \"proto2\";\n"
2180 " optional int32 a = 2;\n"
2181 " extensions 4 to 5;\n"
2182 " optional int64 d = 8;\n"
2185 CreateTempFile(
"baz.proto",
2186 "syntax = \"proto2\";\n"
2188 " optional int32 a = 2;\n"
2189 " optional int64 d = 8;\n"
2190 " extensions 15 to max;\n"
2192 " extensions 10 to 12;\n"
2198 "syntax = \"proto2\";\n"
2201 " optional int32 a = 2;\n"
2202 " optional group C = 4 {\n"
2203 " optional int32 d = 5;\n"
2205 " extensions 8 to 10;\n"
2206 " optional group E = 11 {\n"
2207 " optional int32 f = 9;\n"
2208 " optional group G = 15 {\n"
2214 Run(
"protocol_compiler --print_free_field_numbers --proto_path=$tmpdir "
2215 "foo.proto bar.proto baz.proto quz.proto");
2222 #if !defined(__CYGWIN__)
2223 ExpectCapturedStdout(
2224 "foo.Foo free: 1 3 6-7 9 11-INF\n"
2225 "Bar free: 1 3 6-7 9 11-INF\n"
2226 "Baz free: 1 3 6-7 9 14\n"
2227 "Quz.Foo free: 1-INF\n"
2228 "Quz.E.G.Foo free: 1-INF\n"
2229 "Quz free: 1 3 6-7 12-14 16-INF\n");
2240 enum EncodeDecodeTestMode { PROTO_PATH, DESCRIPTOR_SET_IN };
2244 virtual void SetUp() {
2245 WriteUnittestProtoDescriptorSet();
2249 virtual void TearDown() {
2260 bool RedirectStdinFromFile(
const std::string& filename) {
2261 int fd = open(filename.c_str(), O_RDONLY);
2262 if (fd < 0)
return false;
2263 dup2(fd, STDIN_FILENO);
2272 for (
int i = 0;
i < text.size();
i++) {
2273 if (text[
i] !=
'\r') {
2274 result.push_back(text[
i]);
2281 enum Type { TEXT, BINARY };
2282 enum ReturnCode { SUCCESS,
ERROR };
2285 std::vector<std::string>
args;
2286 args.push_back(
"protoc");
2288 switch (GetParam()) {
2292 case DESCRIPTOR_SET_IN:
2293 args.push_back(
StrCat(
"--descriptor_set_in=",
2297 ADD_FAILURE() <<
"unexpected EncodeDecodeTestMode: " << GetParam();
2300 std::unique_ptr<const char*[]> argv(
new const char*[
args.size()]);
2301 for (
int i = 0;
i <
args.size();
i++) {
2302 argv[
i] =
args[
i].c_str();
2305 CommandLineInterface cli;
2310 int result = cli.Run(
args.size(), argv.get());
2318 void ExpectStdoutMatchesBinaryFile(
const std::string& filename) {
2327 void ExpectStdoutMatchesTextFile(
const std::string& filename) {
2331 ExpectStdoutMatchesText(expected_output);
2334 void ExpectStdoutMatchesText(
const std::string& expected_text) {
2338 void ExpectStderrMatchesText(
const std::string& expected_text) {
2343 void WriteUnittestProtoDescriptorSet() {
2345 TestTempDir() +
"/unittest_proto_descriptor_set.bin";
2347 protobuf_unittest::TestAllTypes test_all_types;
2350 protobuf_unittest_import::ImportMessage import_message;
2351 import_message.descriptor()->file()->CopyTo(file_descriptor_set.
add_file());
2353 protobuf_unittest_import::PublicImportMessage public_import_message;
2354 public_import_message.descriptor()->file()->CopyTo(
2359 GOOGLE_CHECK(file_descriptor_set.SerializeToString(&binary_proto));
2361 binary_proto,
true));
2370 TEST_P(EncodeDecodeTest, Encode) {
2372 "net/proto2/internal/"
2373 "testdata/text_format_unittest_data_oneof_implemented.txt"));
2376 " --encode=protobuf_unittest.TestAllTypes"));
2378 "net/proto2/internal/testdata/golden_message_oneof_implemented"));
2379 ExpectStderrMatchesText(
"");
2382 TEST_P(EncodeDecodeTest, Decode) {
2384 "net/proto2/internal/testdata/golden_message_oneof_implemented"));
2387 " --decode=protobuf_unittest.TestAllTypes"));
2389 "net/proto2/internal/"
2390 "testdata/text_format_unittest_data_oneof_implemented.txt"));
2391 ExpectStderrMatchesText(
"");
2394 TEST_P(EncodeDecodeTest, Partial) {
2395 RedirectStdinFromText(
"");
2398 " --encode=protobuf_unittest.TestRequired"));
2399 ExpectStdoutMatchesText(
"");
2400 ExpectStderrMatchesText(
2401 "warning: Input message is missing required fields: a, b, c\n");
2404 TEST_P(EncodeDecodeTest, DecodeRaw) {
2405 protobuf_unittest::TestAllTypes
message;
2406 message.set_optional_int32(123);
2407 message.set_optional_string(
"foo");
2411 RedirectStdinFromText(
data);
2413 ExpectStdoutMatchesText(
2416 ExpectStderrMatchesText(
"");
2419 TEST_P(EncodeDecodeTest, UnknownType) {
2422 " --encode=NoSuchType"));
2423 ExpectStdoutMatchesText(
"");
2424 ExpectStderrMatchesText(
"Type not defined: NoSuchType\n");
2427 TEST_P(EncodeDecodeTest, ProtoParseError) {
2429 Run(
"net/proto2/internal/no_such_file.proto "
2430 "--encode=NoSuchType"));
2431 ExpectStdoutMatchesText(
"");
2432 ExpectStderrMatchesText(
2433 "net/proto2/internal/no_such_file.proto: No such file or directory\n");
2440 #endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN