summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Gamito <pablogamito@google.com>2024-03-06 13:10:15 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2024-03-06 13:10:15 +0000
commit23a119fc57a1a8ffbb48358d0c6e592861a2802b (patch)
treefe6e4e74d9eba7bd1b8ea58448d820dd515ffd71
parenta15e9ac25f7bd70e8705fd6429035d90720c7963 (diff)
parenta2e44448c17500b7a0b7265ebde218f3fae6d5ed (diff)
downloadbase-23a119fc57a1a8ffbb48358d0c6e592861a2802b.tar.gz
Merge "Add option to only compile certain Proto messages" into main am: a2e44448c1
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2958234 Change-Id: I0fd3f79f3ee0728b55185a0a442aa80e01bc27fa Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--tools/streaming_proto/Android.bp56
-rw-r--r--tools/streaming_proto/java/java_proto_stream_code_generator.cpp339
-rw-r--r--tools/streaming_proto/java/java_proto_stream_code_generator.h29
-rw-r--r--tools/streaming_proto/java/main.cpp278
-rw-r--r--tools/streaming_proto/test/integration/imported.proto (renamed from tools/streaming_proto/test/imported.proto)0
-rw-r--r--tools/streaming_proto/test/integration/src/com/android/streaming_proto_test/Main.java23
-rw-r--r--tools/streaming_proto/test/integration/test.proto (renamed from tools/streaming_proto/test/test.proto)2
-rw-r--r--tools/streaming_proto/test/src/com/android/streaming_proto_test/Main.java7
-rw-r--r--tools/streaming_proto/test/unit/streaming_proto_java.cpp191
9 files changed, 645 insertions, 280 deletions
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
index b18bdff7263f..b1b314fcdb19 100644
--- a/tools/streaming_proto/Android.bp
+++ b/tools/streaming_proto/Android.bp
@@ -17,6 +17,7 @@
// ==========================================================
// Build the host executable: protoc-gen-javastream
// ==========================================================
+
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -41,6 +42,32 @@ cc_defaults {
static_libs: ["libprotoc"],
}
+// ==========================================================
+// Build the host static library: java_streaming_proto_lib
+// ==========================================================
+
+cc_library_host_static {
+ name: "java_streaming_proto_lib",
+ defaults: ["protoc-gen-stream-defaults"],
+ target: {
+ darwin: {
+ cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
+ },
+ },
+ cflags: [
+ "-Wno-format-y2k",
+ "-DSTATIC_ANDROIDFW_FOR_TOOLS",
+ ],
+
+ srcs: [
+ "java/java_proto_stream_code_generator.cpp",
+ ],
+}
+
+// ==========================================================
+// Build the host executable: protoc-gen-javastream
+// ==========================================================
+
cc_binary_host {
name: "protoc-gen-javastream",
srcs: [
@@ -48,8 +75,13 @@ cc_binary_host {
],
defaults: ["protoc-gen-stream-defaults"],
+ static_libs: ["java_streaming_proto_lib"],
}
+// ==========================================================
+// Build the host executable: protoc-gen-cppstream
+// ==========================================================
+
cc_binary_host {
name: "protoc-gen-cppstream",
srcs: [
@@ -60,13 +92,31 @@ cc_binary_host {
}
// ==========================================================
+// Build the host tests: StreamingProtoTest
+// ==========================================================
+
+cc_test_host {
+ name: "StreamingProtoTest",
+ defaults: ["protoc-gen-stream-defaults"],
+ srcs: [
+ "test/unit/**/*.cpp",
+ ],
+ static_libs: [
+ "java_streaming_proto_lib",
+ "libgmock",
+ "libgtest",
+ ],
+}
+
+// ==========================================================
// Build the java test
// ==========================================================
+
java_library {
- name: "StreamingProtoTest",
+ name: "StreamingProtoJavaIntegrationTest",
srcs: [
- "test/**/*.java",
- "test/**/*.proto",
+ "test/integration/**/*.java",
+ "test/integration/**/*.proto",
],
proto: {
type: "stream",
diff --git a/tools/streaming_proto/java/java_proto_stream_code_generator.cpp b/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
new file mode 100644
index 000000000000..9d61111fb5bd
--- /dev/null
+++ b/tools/streaming_proto/java/java_proto_stream_code_generator.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "java_proto_stream_code_generator.h"
+
+#include <stdio.h>
+
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "Errors.h"
+
+using namespace android::stream_proto;
+using namespace google::protobuf::io;
+using namespace std;
+
+/**
+ * If the descriptor gives us a class name, use that. Otherwise make one up from
+ * the filename of the .proto file.
+ */
+static string make_outer_class_name(const FileDescriptorProto& file_descriptor) {
+ string name = file_descriptor.options().java_outer_classname();
+ if (name.size() == 0) {
+ name = to_camel_case(file_base_name(file_descriptor.name()));
+ if (name.size() == 0) {
+ ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE,
+ "Unable to make an outer class name for file: %s",
+ file_descriptor.name().c_str());
+ name = "Unknown";
+ }
+ }
+ return name;
+}
+
+/**
+ * Figure out the package name that we are generating.
+ */
+static string make_java_package(const FileDescriptorProto& file_descriptor) {
+ if (file_descriptor.options().has_java_package()) {
+ return file_descriptor.options().java_package();
+ } else {
+ return file_descriptor.package();
+ }
+}
+
+/**
+ * Figure out the name of the file we are generating.
+ */
+static string make_file_name(const FileDescriptorProto& file_descriptor, const string& class_name) {
+ string const package = make_java_package(file_descriptor);
+ string result;
+ if (package.size() > 0) {
+ result = replace_string(package, '.', '/');
+ result += '/';
+ }
+
+ result += class_name;
+ result += ".java";
+
+ return result;
+}
+
+static string indent_more(const string& indent) {
+ return indent + INDENT;
+}
+
+/**
+ * Write the constants for an enum.
+ */
+static void write_enum(stringstream& text, const EnumDescriptorProto& enu, const string& indent) {
+ const int N = enu.value_size();
+ text << indent << "// enum " << enu.name() << endl;
+ for (int i = 0; i < N; i++) {
+ const EnumValueDescriptorProto& value = enu.value(i);
+ text << indent << "public static final int " << make_constant_name(value.name()) << " = "
+ << value.number() << ";" << endl;
+ }
+ text << endl;
+}
+
+/**
+ * Write a field.
+ */
+static void write_field(stringstream& text, const FieldDescriptorProto& field,
+ const string& indent) {
+ string optional_comment =
+ field.label() == FieldDescriptorProto::LABEL_OPTIONAL ? "optional " : "";
+ string repeated_comment =
+ field.label() == FieldDescriptorProto::LABEL_REPEATED ? "repeated " : "";
+ string proto_type = get_proto_type(field);
+ string packed_comment = field.options().packed() ? " [packed=true]" : "";
+ text << indent << "// " << optional_comment << repeated_comment << proto_type << ' '
+ << field.name() << " = " << field.number() << packed_comment << ';' << endl;
+
+ text << indent << "public static final long " << make_constant_name(field.name()) << " = 0x";
+
+ ios::fmtflags fmt(text.flags());
+ text << setfill('0') << setw(16) << hex << get_field_id(field);
+ text.flags(fmt);
+
+ text << "L;" << endl;
+
+ text << endl;
+}
+
+/**
+ * Write a Message constants class.
+ */
+static void write_message(stringstream& text, const DescriptorProto& message,
+ const string& indent) {
+ int N;
+ const string indented = indent_more(indent);
+
+ text << indent << "// message " << message.name() << endl;
+ text << indent << "public final class " << message.name() << " {" << endl;
+ text << endl;
+
+ // Enums
+ N = message.enum_type_size();
+ for (int i = 0; i < N; i++) {
+ write_enum(text, message.enum_type(i), indented);
+ }
+
+ // Nested classes
+ N = message.nested_type_size();
+ for (int i = 0; i < N; i++) {
+ write_message(text, message.nested_type(i), indented);
+ }
+
+ // Fields
+ N = message.field_size();
+ for (int i = 0; i < N; i++) {
+ write_field(text, message.field(i), indented);
+ }
+
+ text << indent << "}" << endl;
+ text << endl;
+}
+
+/**
+ * Write the contents of a file.
+ *
+ * If there are enums and generate_outer is false, invalid java code will be generated.
+ */
+static void write_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor,
+ const string& filename, bool generate_outer,
+ const vector<EnumDescriptorProto>& enums,
+ const vector<DescriptorProto>& messages) {
+ stringstream text;
+
+ string const package_name = make_java_package(file_descriptor);
+ string const outer_class_name = make_outer_class_name(file_descriptor);
+
+ text << "// Generated by protoc-gen-javastream. DO NOT MODIFY." << endl;
+ text << "// source: " << file_descriptor.name() << endl << endl;
+
+ if (package_name.size() > 0) {
+ if (package_name.size() > 0) {
+ text << "package " << package_name << ";" << endl;
+ text << endl;
+ }
+ }
+
+ // This bit of policy is android api rules specific: Raw proto classes
+ // must never be in the API
+ text << "/** @hide */" << endl;
+ // text << "@android.annotation.TestApi" << endl;
+
+ if (generate_outer) {
+ text << "public final class " << outer_class_name << " {" << endl;
+ text << endl;
+ }
+
+ size_t N;
+ const string indented = generate_outer ? indent_more("") : string();
+
+ N = enums.size();
+ for (size_t i = 0; i < N; i++) {
+ write_enum(text, enums[i], indented);
+ }
+
+ N = messages.size();
+ for (size_t i = 0; i < N; i++) {
+ write_message(text, messages[i], indented);
+ }
+
+ if (generate_outer) {
+ text << "}" << endl;
+ }
+
+ CodeGeneratorResponse::File* file_response = response->add_file();
+ file_response->set_name(filename);
+ file_response->set_content(text.str());
+}
+
+/**
+ * Write one file per class. Put all of the enums into the "outer" class.
+ */
+static void write_multiple_files(CodeGeneratorResponse* response,
+ const FileDescriptorProto& file_descriptor,
+ set<string> messages_to_compile) {
+ // If there is anything to put in the outer class file, create one
+ if (file_descriptor.enum_type_size() > 0) {
+ vector<EnumDescriptorProto> enums;
+ int N = file_descriptor.enum_type_size();
+ for (int i = 0; i < N; i++) {
+ auto enum_full_name =
+ file_descriptor.package() + "." + file_descriptor.enum_type(i).name();
+ if (!messages_to_compile.empty() && !messages_to_compile.count(enum_full_name)) {
+ continue;
+ }
+ enums.push_back(file_descriptor.enum_type(i));
+ }
+
+ vector<DescriptorProto> messages;
+
+ if (messages_to_compile.empty() || !enums.empty()) {
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
+ true, enums, messages);
+ }
+ }
+
+ // For each of the message types, make a file
+ int N = file_descriptor.message_type_size();
+ for (int i = 0; i < N; i++) {
+ vector<EnumDescriptorProto> enums;
+
+ vector<DescriptorProto> messages;
+
+ auto message_full_name =
+ file_descriptor.package() + "." + file_descriptor.message_type(i).name();
+ if (!messages_to_compile.empty() && !messages_to_compile.count(message_full_name)) {
+ continue;
+ }
+ messages.push_back(file_descriptor.message_type(i));
+
+ if (messages_to_compile.empty() || !messages.empty()) {
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, file_descriptor.message_type(i).name()),
+ false, enums, messages);
+ }
+ }
+}
+
+static void write_single_file(CodeGeneratorResponse* response,
+ const FileDescriptorProto& file_descriptor,
+ set<string> messages_to_compile) {
+ int N;
+
+ vector<EnumDescriptorProto> enums;
+ N = file_descriptor.enum_type_size();
+ for (int i = 0; i < N; i++) {
+ auto enum_full_name = file_descriptor.package() + "." + file_descriptor.enum_type(i).name();
+ if (!messages_to_compile.empty() && !messages_to_compile.count(enum_full_name)) {
+ continue;
+ }
+
+ enums.push_back(file_descriptor.enum_type(i));
+ }
+
+ vector<DescriptorProto> messages;
+ N = file_descriptor.message_type_size();
+ for (int i = 0; i < N; i++) {
+ auto message_full_name =
+ file_descriptor.package() + "." + file_descriptor.message_type(i).name();
+
+ if (!messages_to_compile.empty() && !messages_to_compile.count(message_full_name)) {
+ continue;
+ }
+
+ messages.push_back(file_descriptor.message_type(i));
+ }
+
+ if (messages_to_compile.empty() || !enums.empty() || !messages.empty()) {
+ write_file(response, file_descriptor,
+ make_file_name(file_descriptor, make_outer_class_name(file_descriptor)), true,
+ enums, messages);
+ }
+}
+
+static void parse_args_string(stringstream args_string_stream,
+ set<string>* messages_to_compile_out) {
+ string line;
+ while (getline(args_string_stream, line, ';')) {
+ stringstream line_ss(line);
+ string arg_name;
+ getline(line_ss, arg_name, ':');
+ if (arg_name == "include_filter") {
+ string full_message_name;
+ while (getline(line_ss, full_message_name, ',')) {
+ messages_to_compile_out->insert(full_message_name);
+ }
+ } else {
+ ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE, "Unexpected argument '%s'.", arg_name.c_str());
+ }
+ }
+}
+
+CodeGeneratorResponse generate_java_protostream_code(CodeGeneratorRequest request) {
+ CodeGeneratorResponse response;
+
+ set<string> messages_to_compile;
+ auto request_params = request.parameter();
+ if (!request_params.empty()) {
+ parse_args_string(stringstream(request_params), &messages_to_compile);
+ }
+
+ // Build the files we need.
+ const int N = request.proto_file_size();
+ for (int i = 0; i < N; i++) {
+ const FileDescriptorProto& file_descriptor = request.proto_file(i);
+ if (should_generate_for_file(request, file_descriptor.name())) {
+ if (file_descriptor.options().java_multiple_files()) {
+ write_multiple_files(&response, file_descriptor, messages_to_compile);
+ } else {
+ write_single_file(&response, file_descriptor, messages_to_compile);
+ }
+ }
+ }
+
+ return response;
+}
diff --git a/tools/streaming_proto/java/java_proto_stream_code_generator.h b/tools/streaming_proto/java/java_proto_stream_code_generator.h
new file mode 100644
index 000000000000..d2492f75d383
--- /dev/null
+++ b/tools/streaming_proto/java/java_proto_stream_code_generator.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AOSP_MAIN_FRAMEWORKS_BASE_JAVAPROTOSTREAMCODEGENERATOR_H
+#define AOSP_MAIN_FRAMEWORKS_BASE_JAVAPROTOSTREAMCODEGENERATOR_H
+
+#include "stream_proto_utils.h"
+#include "string_utils.h"
+
+using namespace android::stream_proto;
+using namespace google::protobuf::io;
+using namespace std;
+
+CodeGeneratorResponse generate_java_protostream_code(CodeGeneratorRequest request);
+
+#endif // AOSP_MAIN_FRAMEWORKS_BASE_JAVAPROTOSTREAMCODEGENERATOR_H \ No newline at end of file
diff --git a/tools/streaming_proto/java/main.cpp b/tools/streaming_proto/java/main.cpp
index c9c50a561a04..5b35504865f8 100644
--- a/tools/streaming_proto/java/main.cpp
+++ b/tools/streaming_proto/java/main.cpp
@@ -1,268 +1,21 @@
-#include "Errors.h"
-#include "stream_proto_utils.h"
-#include "string_utils.h"
-
#include <stdio.h>
+
#include <iomanip>
#include <iostream>
-#include <sstream>
#include <map>
+#include <sstream>
+#include <string>
+
+#include "Errors.h"
+#include "java_proto_stream_code_generator.h"
+#include "stream_proto_utils.h"
using namespace android::stream_proto;
using namespace google::protobuf::io;
using namespace std;
/**
- * If the descriptor gives us a class name, use that. Otherwise make one up from
- * the filename of the .proto file.
- */
-static string
-make_outer_class_name(const FileDescriptorProto& file_descriptor)
-{
- string name = file_descriptor.options().java_outer_classname();
- if (name.size() == 0) {
- name = to_camel_case(file_base_name(file_descriptor.name()));
- if (name.size() == 0) {
- ERRORS.Add(UNKNOWN_FILE, UNKNOWN_LINE,
- "Unable to make an outer class name for file: %s",
- file_descriptor.name().c_str());
- name = "Unknown";
- }
- }
- return name;
-}
-
-/**
- * Figure out the package name that we are generating.
- */
-static string
-make_java_package(const FileDescriptorProto& file_descriptor) {
- if (file_descriptor.options().has_java_package()) {
- return file_descriptor.options().java_package();
- } else {
- return file_descriptor.package();
- }
-}
-
-/**
- * Figure out the name of the file we are generating.
- */
-static string
-make_file_name(const FileDescriptorProto& file_descriptor, const string& class_name)
-{
- string const package = make_java_package(file_descriptor);
- string result;
- if (package.size() > 0) {
- result = replace_string(package, '.', '/');
- result += '/';
- }
-
- result += class_name;
- result += ".java";
-
- return result;
-}
-
-static string
-indent_more(const string& indent)
-{
- return indent + INDENT;
-}
-
-/**
- * Write the constants for an enum.
- */
-static void
-write_enum(stringstream& text, const EnumDescriptorProto& enu, const string& indent)
-{
- const int N = enu.value_size();
- text << indent << "// enum " << enu.name() << endl;
- for (int i=0; i<N; i++) {
- const EnumValueDescriptorProto& value = enu.value(i);
- text << indent << "public static final int "
- << make_constant_name(value.name())
- << " = " << value.number() << ";" << endl;
- }
- text << endl;
-}
-
-/**
- * Write a field.
- */
-static void
-write_field(stringstream& text, const FieldDescriptorProto& field, const string& indent)
-{
- string optional_comment = field.label() == FieldDescriptorProto::LABEL_OPTIONAL
- ? "optional " : "";
- string repeated_comment = field.label() == FieldDescriptorProto::LABEL_REPEATED
- ? "repeated " : "";
- string proto_type = get_proto_type(field);
- string packed_comment = field.options().packed()
- ? " [packed=true]" : "";
- text << indent << "// " << optional_comment << repeated_comment << proto_type << ' '
- << field.name() << " = " << field.number() << packed_comment << ';' << endl;
-
- text << indent << "public static final long " << make_constant_name(field.name()) << " = 0x";
-
- ios::fmtflags fmt(text.flags());
- text << setfill('0') << setw(16) << hex << get_field_id(field);
- text.flags(fmt);
-
- text << "L;" << endl;
-
- text << endl;
-}
-
-/**
- * Write a Message constants class.
- */
-static void
-write_message(stringstream& text, const DescriptorProto& message, const string& indent)
-{
- int N;
- const string indented = indent_more(indent);
-
- text << indent << "// message " << message.name() << endl;
- text << indent << "public final class " << message.name() << " {" << endl;
- text << endl;
-
- // Enums
- N = message.enum_type_size();
- for (int i=0; i<N; i++) {
- write_enum(text, message.enum_type(i), indented);
- }
-
- // Nested classes
- N = message.nested_type_size();
- for (int i=0; i<N; i++) {
- write_message(text, message.nested_type(i), indented);
- }
-
- // Fields
- N = message.field_size();
- for (int i=0; i<N; i++) {
- write_field(text, message.field(i), indented);
- }
-
- text << indent << "}" << endl;
- text << endl;
-}
-
-/**
- * Write the contents of a file.
*
- * If there are enums and generate_outer is false, invalid java code will be generated.
- */
-static void
-write_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor,
- const string& filename, bool generate_outer,
- const vector<EnumDescriptorProto>& enums, const vector<DescriptorProto>& messages)
-{
- stringstream text;
-
- string const package_name = make_java_package(file_descriptor);
- string const outer_class_name = make_outer_class_name(file_descriptor);
-
- text << "// Generated by protoc-gen-javastream. DO NOT MODIFY." << endl;
- text << "// source: " << file_descriptor.name() << endl << endl;
-
- if (package_name.size() > 0) {
- if (package_name.size() > 0) {
- text << "package " << package_name << ";" << endl;
- text << endl;
- }
- }
-
- // This bit of policy is android api rules specific: Raw proto classes
- // must never be in the API
- text << "/** @hide */" << endl;
-// text << "@android.annotation.TestApi" << endl;
-
- if (generate_outer) {
- text << "public final class " << outer_class_name << " {" << endl;
- text << endl;
- }
-
- size_t N;
- const string indented = generate_outer ? indent_more("") : string();
-
- N = enums.size();
- for (size_t i=0; i<N; i++) {
- write_enum(text, enums[i], indented);
- }
-
- N = messages.size();
- for (size_t i=0; i<N; i++) {
- write_message(text, messages[i], indented);
- }
-
- if (generate_outer) {
- text << "}" << endl;
- }
-
- CodeGeneratorResponse::File* file_response = response->add_file();
- file_response->set_name(filename);
- file_response->set_content(text.str());
-}
-
-/**
- * Write one file per class. Put all of the enums into the "outer" class.
- */
-static void
-write_multiple_files(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor)
-{
- // If there is anything to put in the outer class file, create one
- if (file_descriptor.enum_type_size() > 0) {
- vector<EnumDescriptorProto> enums;
- int N = file_descriptor.enum_type_size();
- for (int i=0; i<N; i++) {
- enums.push_back(file_descriptor.enum_type(i));
- }
-
- vector<DescriptorProto> messages;
-
- write_file(response, file_descriptor,
- make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
- true, enums, messages);
- }
-
- // For each of the message types, make a file
- int N = file_descriptor.message_type_size();
- for (int i=0; i<N; i++) {
- vector<EnumDescriptorProto> enums;
-
- vector<DescriptorProto> messages;
- messages.push_back(file_descriptor.message_type(i));
-
- write_file(response, file_descriptor,
- make_file_name(file_descriptor, file_descriptor.message_type(i).name()),
- false, enums, messages);
- }
-}
-
-static void
-write_single_file(CodeGeneratorResponse* response, const FileDescriptorProto& file_descriptor)
-{
- int N;
-
- vector<EnumDescriptorProto> enums;
- N = file_descriptor.enum_type_size();
- for (int i=0; i<N; i++) {
- enums.push_back(file_descriptor.enum_type(i));
- }
-
- vector<DescriptorProto> messages;
- N = file_descriptor.message_type_size();
- for (int i=0; i<N; i++) {
- messages.push_back(file_descriptor.message_type(i));
- }
-
- write_file(response, file_descriptor,
- make_file_name(file_descriptor, make_outer_class_name(file_descriptor)),
- true, enums, messages);
-}
-
-/**
* Main.
*/
int
@@ -273,24 +26,11 @@ main(int argc, char const*const* argv)
GOOGLE_PROTOBUF_VERIFY_VERSION;
- CodeGeneratorRequest request;
- CodeGeneratorResponse response;
-
// Read the request
+ CodeGeneratorRequest request;
request.ParseFromIstream(&cin);
- // Build the files we need.
- const int N = request.proto_file_size();
- for (int i=0; i<N; i++) {
- const FileDescriptorProto& file_descriptor = request.proto_file(i);
- if (should_generate_for_file(request, file_descriptor.name())) {
- if (file_descriptor.options().java_multiple_files()) {
- write_multiple_files(&response, file_descriptor);
- } else {
- write_single_file(&response, file_descriptor);
- }
- }
- }
+ CodeGeneratorResponse response = generate_java_protostream_code(request);
// If we had errors, don't write the response. Print the errors and exit.
if (ERRORS.HasErrors()) {
diff --git a/tools/streaming_proto/test/imported.proto b/tools/streaming_proto/test/integration/imported.proto
index 05c8f0c54fac..05c8f0c54fac 100644
--- a/tools/streaming_proto/test/imported.proto
+++ b/tools/streaming_proto/test/integration/imported.proto
diff --git a/tools/streaming_proto/test/integration/src/com/android/streaming_proto_test/Main.java b/tools/streaming_proto/test/integration/src/com/android/streaming_proto_test/Main.java
new file mode 100644
index 000000000000..2a7001b294ea
--- /dev/null
+++ b/tools/streaming_proto/test/integration/src/com/android/streaming_proto_test/Main.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.streaming_proto_test;
+
+public class Main {
+ public void main(String[] argv) {
+ System.out.println("hello world");
+ }
+}
diff --git a/tools/streaming_proto/test/test.proto b/tools/streaming_proto/test/integration/test.proto
index de80ed6612fc..3cf81b4ffd56 100644
--- a/tools/streaming_proto/test/test.proto
+++ b/tools/streaming_proto/test/integration/test.proto
@@ -16,7 +16,7 @@
syntax = "proto2";
-import "frameworks/base/tools/streaming_proto/test/imported.proto";
+import "frameworks/base/tools/streaming_proto/test/integration/imported.proto";
package com.android.streaming_proto_test;
diff --git a/tools/streaming_proto/test/src/com/android/streaming_proto_test/Main.java b/tools/streaming_proto/test/src/com/android/streaming_proto_test/Main.java
deleted file mode 100644
index 1246f539b44b..000000000000
--- a/tools/streaming_proto/test/src/com/android/streaming_proto_test/Main.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.android.streaming_proto_test;
-
-public class Main {
- public void main(String[] argv) {
- System.out.println("hello world");
- }
-}
diff --git a/tools/streaming_proto/test/unit/streaming_proto_java.cpp b/tools/streaming_proto/test/unit/streaming_proto_java.cpp
new file mode 100644
index 000000000000..8df9716b312d
--- /dev/null
+++ b/tools/streaming_proto/test/unit/streaming_proto_java.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "java/java_proto_stream_code_generator.h"
+
+using ::testing::HasSubstr;
+using ::testing::Not;
+
+static void add_my_test_proto_file(CodeGeneratorRequest* request) {
+ request->add_file_to_generate("MyTestProtoFile");
+
+ FileDescriptorProto* file_desc = request->add_proto_file();
+ file_desc->set_name("MyTestProtoFile");
+ file_desc->set_package("test.package");
+
+ auto* file_options = file_desc->mutable_options();
+ file_options->set_java_multiple_files(false);
+
+ auto* message = file_desc->add_message_type();
+ message->set_name("MyTestMessage");
+
+ auto* field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("my_test_field");
+
+ field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("my_other_test_field");
+
+ field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("my_other_test_message");
+}
+
+static void add_my_other_test_proto_file(CodeGeneratorRequest* request) {
+ request->add_file_to_generate("MyOtherTestProtoFile");
+
+ FileDescriptorProto* file_desc = request->add_proto_file();
+ file_desc->set_name("MyOtherTestProtoFile");
+ file_desc->set_package("test.package");
+
+ auto* file_options = file_desc->mutable_options();
+ file_options->set_java_multiple_files(false);
+
+ auto* message = file_desc->add_message_type();
+ message->set_name("MyOtherTestMessage");
+
+ auto* field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("a_test_field");
+
+ field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("another_test_field");
+}
+
+static CodeGeneratorRequest create_simple_two_file_request() {
+ CodeGeneratorRequest request;
+
+ add_my_test_proto_file(&request);
+ add_my_other_test_proto_file(&request);
+
+ return request;
+}
+
+static CodeGeneratorRequest create_simple_multi_file_request() {
+ CodeGeneratorRequest request;
+
+ request.add_file_to_generate("MyMultiMessageTestProtoFile");
+
+ FileDescriptorProto* file_desc = request.add_proto_file();
+ file_desc->set_name("MyMultiMessageTestProtoFile");
+ file_desc->set_package("test.package");
+
+ auto* file_options = file_desc->mutable_options();
+ file_options->set_java_multiple_files(true);
+
+ auto* message = file_desc->add_message_type();
+ message->set_name("MyTestMessage");
+
+ auto* field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("my_test_field");
+
+ field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("my_other_test_field");
+
+ field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("my_other_test_message");
+
+ message = file_desc->add_message_type();
+ message->set_name("MyOtherTestMessage");
+
+ field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("a_test_field");
+
+ field = message->add_field();
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ field->set_name("another_test_field");
+
+ return request;
+}
+
+TEST(StreamingProtoJavaTest, NoFilter) {
+ CodeGeneratorRequest request = create_simple_two_file_request();
+ CodeGeneratorResponse response = generate_java_protostream_code(request);
+
+ auto generated_file_count = response.file_size();
+ EXPECT_EQ(generated_file_count, 2);
+
+ EXPECT_EQ(response.file(0).name(), "test/package/MyTestProtoFile.java");
+ EXPECT_THAT(response.file(0).content(), HasSubstr("class MyTestProtoFile"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("class MyTestMessage"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_TEST_FIELD"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_OTHER_TEST_FIELD"));
+
+ EXPECT_EQ(response.file(1).name(), "test/package/MyOtherTestProtoFile.java");
+ EXPECT_THAT(response.file(1).content(), HasSubstr("class MyOtherTestProtoFile"));
+ EXPECT_THAT(response.file(1).content(), HasSubstr("class MyOtherTestMessage"));
+ EXPECT_THAT(response.file(1).content(), HasSubstr("long A_TEST_FIELD"));
+ EXPECT_THAT(response.file(1).content(), HasSubstr("long ANOTHER_TEST_FIELD"));
+}
+
+TEST(StreamingProtoJavaTest, WithFilter) {
+ CodeGeneratorRequest request = create_simple_two_file_request();
+ request.set_parameter("include_filter:test.package.MyTestMessage");
+ CodeGeneratorResponse response = generate_java_protostream_code(request);
+
+ auto generated_file_count = response.file_size();
+ EXPECT_EQ(generated_file_count, 1);
+
+ EXPECT_EQ(response.file(0).name(), "test/package/MyTestProtoFile.java");
+ EXPECT_THAT(response.file(0).content(), HasSubstr("class MyTestProtoFile"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("class MyTestMessage"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_TEST_FIELD"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_OTHER_TEST_FIELD"));
+}
+
+TEST(StreamingProtoJavaTest, WithoutFilter_MultipleJavaFiles) {
+ CodeGeneratorRequest request = create_simple_multi_file_request();
+ CodeGeneratorResponse response = generate_java_protostream_code(request);
+
+ auto generated_file_count = response.file_size();
+ EXPECT_EQ(generated_file_count, 2);
+
+ EXPECT_EQ(response.file(0).name(), "test/package/MyTestMessage.java");
+ EXPECT_THAT(response.file(0).content(), Not(HasSubstr("class MyTestProtoFile")));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("class MyTestMessage"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_TEST_FIELD"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_OTHER_TEST_FIELD"));
+
+ EXPECT_EQ(response.file(1).name(), "test/package/MyOtherTestMessage.java");
+ EXPECT_THAT(response.file(1).content(), Not(HasSubstr("class MyOtherTestProtoFile")));
+ EXPECT_THAT(response.file(1).content(), HasSubstr("class MyOtherTestMessage"));
+ EXPECT_THAT(response.file(1).content(), HasSubstr("long A_TEST_FIELD"));
+ EXPECT_THAT(response.file(1).content(), HasSubstr("long ANOTHER_TEST_FIELD"));
+}
+
+TEST(StreamingProtoJavaTest, WithFilter_MultipleJavaFiles) {
+ CodeGeneratorRequest request = create_simple_multi_file_request();
+ request.set_parameter("include_filter:test.package.MyTestMessage");
+ CodeGeneratorResponse response = generate_java_protostream_code(request);
+
+ auto generated_file_count = response.file_size();
+ EXPECT_EQ(generated_file_count, 1);
+
+ EXPECT_EQ(response.file(0).name(), "test/package/MyTestMessage.java");
+ EXPECT_THAT(response.file(0).content(), Not(HasSubstr("class MyTestProtoFile")));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("class MyTestMessage"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_TEST_FIELD"));
+ EXPECT_THAT(response.file(0).content(), HasSubstr("long MY_OTHER_TEST_FIELD"));
+}