diff options
36 files changed, 688 insertions, 906 deletions
@@ -79,7 +79,8 @@ src/**/*.log src/**/*.trs # JavaBuild output. -java/target +java/core/target +java/util/target javanano/target # Windows native output. @@ -135,3 +136,11 @@ php/ext/google/protobuf/configure.in php/ext/google/protobuf/mkinstalldirs php/ext/google/protobuf/run-tests.php vendor/ + +# JavaScript artifacts +js/commonjs_out/ +js/deps.js +js/google-protobuf.js +js/google/ +js/node_modules/ +js/testproto_libs.js diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..55a47cea --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/benchmark"] + path = third_party/benchmark + url = https://github.com/google/benchmark.git diff --git a/.travis.yml b/.travis.yml index fd54ed1f..bd9a5dfb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ sudo: required +dist: trusty # Note: travis currently does not support listing more than one language so # this cheats and claims to only be cpp. If they add multiple language # support, this should probably get updated to install steps and/or @@ -7,7 +8,7 @@ language: cpp os: - osx # The Objective C build needs Xcode 7.0 or later. -osx_image: xcode7.3 +osx_image: xcode8 script: - ./tests.sh $CONFIG env: @@ -14,7 +14,7 @@ COPTS = [ "-Wwrite-strings", "-Woverloaded-virtual", "-Wno-sign-compare", - "-Wno-error=unused-function", + "-Wno-unused-function", ] config_setting( diff --git a/Makefile.am b/Makefile.am index de197088..7e47a119 100644 --- a/Makefile.am +++ b/Makefile.am @@ -729,7 +729,6 @@ python_EXTRA_DIST= \ ruby_EXTRA_DIST= \ ruby/Gemfile \ - ruby/Gemfile.lock \ ruby/.gitignore \ ruby/README.md \ ruby/Rakefile \ @@ -1,7 +1,7 @@ Protocol Buffers - Google's data interchange format =================================================== -[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) [![Build Status](https://grpc-testing.appspot.com/buildStatus/icon?job=protobuf_branch)](https://grpc-testing.appspot.com/job/protobuf_branch) +[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf) [![Build Status](https://grpc-testing.appspot.com/buildStatus/icon?job=protobuf_branch)](https://grpc-testing.appspot.com/job/protobuf_branch) [![Build Status](https://grpc-testing.appspot.com/job/protobuf_branch_32/badge/icon)](https://grpc-testing.appspot.com/job/protobuf_branch_32) Copyright 2008 Google Inc. diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am index f730afe5..d98eae5e 100644 --- a/benchmarks/Makefile.am +++ b/benchmarks/Makefile.am @@ -16,7 +16,9 @@ benchmarks_protoc_outputs_proto2 = \ benchmark_messages_proto2.pb.cc \ benchmark_messages_proto2.pb.h -bin_PROGRAMS = generate-datasets +AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare + +bin_PROGRAMS = generate-datasets cpp-benchmark generate_datasets_LDADD = $(top_srcdir)/src/libprotobuf.la generate_datasets_SOURCES = generate_datasets.cc @@ -30,6 +32,13 @@ nodist_generate_datasets_SOURCES = \ # See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually generate_datasets-generate_datasets.$(OBJEXT): benchmarks.pb.h +cpp_benchmark_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a +cpp_benchmark_SOURCES = cpp_benchmark.cc +cpp_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir) -I$(top_srcdir)/third_party/benchmark/include +nodist_cpp_benchmark_SOURCES = \ + $(benchmarks_protoc_outputs) \ + $(benchmarks_protoc_outputs_proto2) + $(benchmarks_protoc_outputs): protoc_middleman $(benchmarks_protoc_outputs_proto2): protoc_middleman2 diff --git a/benchmarks/benchmark_messages_proto2.proto b/benchmarks/benchmark_messages_proto2.proto index 01f67a1a..59085503 100644 --- a/benchmarks/benchmark_messages_proto2.proto +++ b/benchmarks/benchmark_messages_proto2.proto @@ -8,6 +8,8 @@ option java_package = "com.google.protobuf.benchmarks"; // This is the default, but we specify it here explicitly. option optimize_for = SPEED; +option cc_enable_arenas = true; + message GoogleMessage1 { required string field1 = 1; optional string field9 = 9; diff --git a/benchmarks/benchmark_messages_proto3.proto b/benchmarks/benchmark_messages_proto3.proto index 32f58698..090b554b 100644 --- a/benchmarks/benchmark_messages_proto3.proto +++ b/benchmarks/benchmark_messages_proto3.proto @@ -8,6 +8,8 @@ option java_package = "com.google.protobuf.benchmarks"; // This is the default, but we specify it here explicitly. option optimize_for = SPEED; +option cc_enable_arenas = true; + message GoogleMessage1 { string field1 = 1; string field9 = 9; diff --git a/benchmarks/cpp_benchmark.cc b/benchmarks/cpp_benchmark.cc new file mode 100644 index 00000000..0e6febc2 --- /dev/null +++ b/benchmarks/cpp_benchmark.cc @@ -0,0 +1,242 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <glob.h> +#include <iostream> +#include <fstream> +#include "benchmark/benchmark_api.h" +#include "benchmarks.pb.h" +#include "benchmark_messages_proto2.pb.h" +#include "benchmark_messages_proto3.pb.h" + +#define PREFIX "dataset." +#define SUFFIX ".pb" + +using benchmarks::BenchmarkDataset; +using google::protobuf::Arena; +using google::protobuf::Descriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::Message; +using google::protobuf::MessageFactory; + +class Fixture : public benchmark::Fixture { + public: + Fixture(const BenchmarkDataset& dataset, const std::string& suffix) { + for (int i = 0; i < dataset.payload_size(); i++) { + payloads_.push_back(dataset.payload(i)); + } + + const Descriptor* d = + DescriptorPool::generated_pool()->FindMessageTypeByName( + dataset.message_name()); + + if (!d) { + std::cerr << "Couldn't find message named '" << dataset.message_name() + << "\n"; + } + + prototype_ = MessageFactory::generated_factory()->GetPrototype(d); + SetName((dataset.name() + suffix).c_str()); + } + + protected: + std::vector<std::string> payloads_; + const Message* prototype_; +}; + +class WrappingCounter { + public: + WrappingCounter(size_t limit) : value_(0), limit_(limit) {} + + size_t Next() { + size_t ret = value_; + if (++value_ == limit_) { + value_ = 0; + } + return ret; + } + + private: + size_t value_; + size_t limit_; +}; + +template <class T> +class ParseNewFixture : public Fixture { + public: + ParseNewFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_parse_new") {} + + virtual void BenchmarkCase(benchmark::State& state) { + WrappingCounter i(payloads_.size()); + size_t total = 0; + + while (state.KeepRunning()) { + T m; + const std::string& payload = payloads_[i.Next()]; + total += payload.size(); + m.ParseFromString(payload); + } + + state.SetBytesProcessed(total); + } +}; + +template <class T> +class ParseNewArenaFixture : public Fixture { + public: + ParseNewArenaFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_parse_newarena") {} + + virtual void BenchmarkCase(benchmark::State& state) { + WrappingCounter i(payloads_.size()); + size_t total = 0; + + while (state.KeepRunning()) { + Arena arena; + Message* m = Arena::CreateMessage<T>(&arena); + const std::string& payload = payloads_[i.Next()]; + total += payload.size(); + m->ParseFromString(payload); + } + + state.SetBytesProcessed(total); + } +}; + +template <class T> +class ParseReuseFixture : public Fixture { + public: + ParseReuseFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_parse_reuse") {} + + virtual void BenchmarkCase(benchmark::State& state) { + T m; + WrappingCounter i(payloads_.size()); + size_t total = 0; + + while (state.KeepRunning()) { + const std::string& payload = payloads_[i.Next()]; + total += payload.size(); + m.ParseFromString(payload); + } + + state.SetBytesProcessed(total); + } +}; + +template <class T> +class SerializeFixture : public Fixture { + public: + SerializeFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_serialize") { + for (size_t i = 0; i < payloads_.size(); i++) { + message_.push_back(new T); + message_.back()->ParseFromString(payloads_[i]); + } + } + + ~SerializeFixture() { + for (size_t i = 0; i < message_.size(); i++) { + delete message_[i]; + } + } + + virtual void BenchmarkCase(benchmark::State& state) { + size_t total = 0; + std::string str; + WrappingCounter i(payloads_.size()); + + while (state.KeepRunning()) { + str.clear(); + message_[i.Next()]->SerializeToString(&str); + total += str.size(); + } + + state.SetBytesProcessed(total); + } + + private: + std::vector<T*> message_; +}; + +std::string ReadFile(const std::string& name) { + std::ifstream file(name.c_str()); + GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" << name << + "', please make sure you are running " + "this command from the benchmarks/ " + "directory.\n"; + return std::string((std::istreambuf_iterator<char>(file)), + std::istreambuf_iterator<char>()); +} + +template <class T> +void RegisterBenchmarksForType(const BenchmarkDataset& dataset) { + ::benchmark::internal::RegisterBenchmarkInternal( + new ParseNewFixture<T>(dataset)); + ::benchmark::internal::RegisterBenchmarkInternal( + new ParseReuseFixture<T>(dataset)); + ::benchmark::internal::RegisterBenchmarkInternal( + new ParseNewArenaFixture<T>(dataset)); + ::benchmark::internal::RegisterBenchmarkInternal( + new SerializeFixture<T>(dataset)); +} + +void RegisterBenchmarks(const std::string& dataset_bytes) { + BenchmarkDataset dataset; + GOOGLE_CHECK(dataset.ParseFromString(dataset_bytes)); + + if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") { + RegisterBenchmarksForType<benchmarks::proto3::GoogleMessage1>(dataset); + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") { + RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage1>(dataset); + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { + RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage2>(dataset); + } else { + std::cerr << "Unknown message type: " << dataset.message_name(); + exit(1); + } +} + +int main(int argc, char *argv[]) { + glob_t glob_result; + if (glob("dataset.*.pb", 0, NULL, &glob_result) != 0) { + fprintf(stderr, "No dataset files found.\n"); + return 1; + } + + for (size_t i = 0; i < glob_result.gl_pathc; i++) { + fprintf(stderr, "Found input dataset: %s\n", glob_result.gl_pathv[i]); + RegisterBenchmarks(ReadFile(glob_result.gl_pathv[i])); + } + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); +} diff --git a/docs/swift/DesignDoc.md b/docs/swift/DesignDoc.md deleted file mode 100644 index 364a4d3f..00000000 --- a/docs/swift/DesignDoc.md +++ /dev/null @@ -1,674 +0,0 @@ -# Protocol Buffers in Swift - -## Objective - -This document describes the user-facing API and internal implementation of -proto2 and proto3 messages in Apple’s Swift programming language. - -One of the key goals of protobufs is to provide idiomatic APIs for each -language. In that vein, **interoperability with Objective-C is a non-goal of -this proposal.** Protobuf users who need to pass messages between Objective-C -and Swift code in the same application should use the existing Objective-C proto -library. The goal of the effort described here is to provide an API for protobuf -messages that uses features specific to Swift—optional types, algebraic -enumerated types, value types, and so forth—in a natural way that will delight, -rather than surprise, users of the language. - -## Naming - -* By convention, both typical protobuf message names and Swift structs/classes - are `UpperCamelCase`, so for most messages, the name of a message can be the - same as the name of its generated type. (However, see the discussion below - about prefixes under [Packages](#packages).) - -* Enum cases in protobufs typically are `UPPERCASE_WITH_UNDERSCORES`, whereas - in Swift they are `lowerCamelCase` (as of the Swift 3 API design - guidelines). We will transform the names to match Swift convention, using - a whitelist similar to the Objective-C compiler plugin to handle commonly - used acronyms. - -* Typical fields in proto messages are `lowercase_with_underscores`, while in - Swift they are `lowerCamelCase`. We will transform the names to match - Swift convention by removing the underscores and uppercasing the subsequent - letter. - -## Swift reserved words - -Swift has a large set of reserved words—some always reserved and some -contextually reserved (that is, they can be used as identifiers in contexts -where they would not be confused). As of Swift 2.2, the set of always-reserved -words is: - -``` -_, #available, #column, #else, #elseif, #endif, #file, #function, #if, #line, -#selector, as, associatedtype, break, case, catch, class, continue, default, -defer, deinit, do, dynamicType, else, enum, extension, fallthrough, false, for, -func, guard, if, import, in, init, inout, internal, is, let, nil, operator, -private, protocol, public, repeat, rethrows, return, self, Self, static, -struct, subscript, super, switch, throw, throws, true, try, typealias, var, -where, while -``` - -The set of contextually reserved words is: - -``` -associativity, convenience, dynamic, didSet, final, get, infix, indirect, -lazy, left, mutating, none, nonmutating, optional, override, postfix, -precedence, prefix, Protocol, required, right, set, Type, unowned, weak, -willSet -``` - -It is possible to use any reserved word as an identifier by escaping it with -backticks (for example, ``let `class` = 5``). Other name-mangling schemes would -require us to transform the names themselves (for example, by appending an -underscore), which requires us to then ensure that the new name does not collide -with something else in the same namespace. - -While the backtick feature may not be widely known by all Swift developers, a -small amount of user education can address this and it seems like the best -approach. We can unconditionally surround all property names with backticks to -simplify generation. - -Some remapping will still be required, though, to avoid collisions between -generated properties and the names of methods and properties defined in the base -protocol/implementation of messages. - -# Features of Protocol Buffers - -This section describes how the features of the protocol buffer syntaxes (proto2 -and proto3) map to features in Swift—what the code generated from a proto will -look like, and how it will be implemented in the underlying library. - -## Packages - -Modules are the main form of namespacing in Swift, but they are not declared -using syntactic constructs like namespaces in C++ or packages in Java. Instead, -they are tied to build targets in Xcode (or, in the future with open-source -Swift, declarations in a Swift Package Manager manifest). They also do not -easily support nesting submodules (Clang module maps support this, but pure -Swift does not yet provide a way to define submodules). - -We will generate types with fully-qualified underscore-delimited names. For -example, a message `Baz` in package `foo.bar` would generate a struct named -`Foo_Bar_Baz`. For each fully-qualified proto message, there will be exactly one -unique type symbol emitted in the generated binary. - -Users are likely to balk at the ugliness of underscore-delimited names for every -generated type. To improve upon this situation, we will add a new string file -level option, `swift_package_typealias`, that can be added to `.proto` files. -When present, this will cause `typealias`es to be added to the generated Swift -messages that replace the package name prefix with the provided string. For -example, the following `.proto` file: - -```protobuf -option swift_package_typealias = "FBP"; -package foo.bar; - -message Baz { - // Message fields -} -``` - -would generate the following Swift source: - -```swift -public struct Foo_Bar_Baz { - // Message fields and other methods -} - -typealias FBPBaz = Foo_Bar_Baz -``` - -It should be noted that this type alias is recorded in the generated -`.swiftmodule` so that code importing the module can refer to it, but it does -not cause a new symbol to be generated in the compiled binary (i.e., we do not -risk compiled size bloat by adding `typealias`es for every type). - -Other strategies to handle packages that were considered and rejected can be -found in [Appendix A](#appendix-a-rejected-strategies-to-handle-packages). - -## Messages - -Proto messages are natural value types and we will generate messages as structs -instead of classes. Users will benefit from Swift’s built-in behavior with -regard to mutability. We will define a `ProtoMessage` protocol that defines the -common methods and properties for all messages (such as serialization) and also -lets users treat messages polymorphically. Any shared method implementations -that do not differ between individual messages can be implemented in a protocol -extension. - -The backing storage itself for fields of a message will be managed by a -`ProtoFieldStorage` type that uses an internal dictionary keyed by field number, -and whose values are the value of the field with that number (up-cast to Swift’s -`Any` type). This class will provide type-safe getters and setters so that -generated messages can manipulate this storage, and core serialization logic -will live here as well. Furthermore, factoring the storage out into a separate -type, rather than inlining the fields as stored properties in the message -itself, lets us implement copy-on-write efficiently to support passing around -large messages. (Furthermore, because the messages themselves are value types, -inlining fields is not possible if the fields are submessages of the same type, -or a type that eventually includes a submessage of the same type.) - -### Required fields (proto2 only) - -Required fields in proto2 messages seem like they could be naturally represented -by non-optional properties in Swift, but this presents some problems/concerns. - -Serialization APIs permit partial serialization, which allows required fields to -remain unset. Furthermore, other language APIs still provide `has*` and `clear*` -methods for required fields, and knowing whether a property has a value when the -message is in memory is still useful. - -For example, an e-mail draft message may have the “to” address required on the -wire, but when the user constructs it in memory, it doesn’t make sense to force -a value until they provide one. We only want to force a value to be present when -the message is serialized to the wire. Using non-optional properties prevents -this use case, and makes client usage awkward because the user would be forced -to select a sentinel or placeholder value for any required fields at the time -the message was created. - -### Default values - -In proto2, fields can have a default value specified that may be a value other -than the default value for its corresponding language type (for example, a -default value of 5 instead of 0 for an integer). When reading a field that is -not explicitly set, the user expects to get that value. This makes Swift -optionals (i.e., `Foo?`) unsuitable for fields in general. Unfortunately, we -cannot implement our own “enhanced optional” type without severely complicating -usage (Swift’s use of type inference and its lack of implicit conversions would -require manual unwrapping of every property value). - -Instead, we can use **implicitly unwrapped optionals.** For example, a property -generated for a field of type `int32` would have Swift type `Int32!`. These -properties would behave with the following characteristics, which mirror the -nil-resettable properties used elsewhere in Apple’s SDKs (for example, -`UIView.tintColor`): - -* Assigning a non-nil value to a property sets the field to that value. -* Assigning nil to a property clears the field (its internal representation is - nilled out). -* Reading the value of a property returns its value if it is set, or returns - its default value if it is not set. Reading a property never returns nil. - -The final point in the list above implies that the optional cannot be checked to -determine if the field is set to a value other than its default: it will never -be nil. Instead, we must provide `has*` methods for each field to allow the user -to check this. These methods will be public in proto2. In proto3, these methods -will be private (if generated at all), since the user can test the returned -value against the zero value for that type. - -### Autocreation of nested messages - -For convenience, dotting into an unset field representing a nested message will -return an instance of that message with default values. As in the Objective-C -implementation, this does not actually cause the field to be set until the -returned message is mutated. Fortunately, thanks to the way mutability of value -types is implemented in Swift, the language automatically handles the -reassignment-on-mutation for us. A static singleton instance containing default -values can be associated with each message that can be returned when reading, so -copies are only made by the Swift runtime when mutation occurs. For example, -given the following proto: - -```protobuf -message Node { - Node child = 1; - string value = 2 [default = "foo"]; -} -``` - -The following Swift code would act as commented, where setting deeply nested -properties causes the copies and mutations to occur as the assignment statement -is unwound: - -```swift -var node = Node() - -let s = node.child.child.value -// 1. node.child returns the "default Node". -// 2. Reading .child on the result of (1) returns the same default Node. -// 3. Reading .value on the result of (2) returns the default value "foo". - -node.child.child.value = "bar" -// 4. Setting .value on the default Node causes a copy to be made and sets -// the property on that copy. Subsequently, the language updates the -// value of "node.child.child" to point to that copy. -// 5. Updating "node.child.child" in (4) requires another copy, because -// "node.child" was also the instance of the default node. The copy is -// assigned back to "node.child". -// 6. Setting "node.child" in (5) is a simple value reassignment, since -// "node" is a mutable var. -``` - -In other words, the generated messages do not internally have to manage parental -relationships to backfill the appropriate properties on mutation. Swift provides -this for free. - -## Scalar value fields - -Proto scalar value fields will map to Swift types in the following way: - -.proto Type | Swift Type ------------ | ------------------- -`double` | `Double` -`float` | `Float` -`int32` | `Int32` -`int64` | `Int64` -`uint32` | `UInt32` -`uint64` | `UInt64` -`sint32` | `Int32` -`sint64` | `Int64` -`fixed32` | `UInt32` -`fixed64` | `UInt64` -`sfixed32` | `Int32` -`sfixed64` | `Int64` -`bool` | `Bool` -`string` | `String` -`bytes` | `Foundation.NSData` - -The proto spec defines a number of integral types that map to the same Swift -type; for example, `intXX`, `sintXX`, and `sfixedXX` are all signed integers, -and `uintXX` and `fixedXX` are both unsigned integers. No other language -implementation distinguishes these further, so we do not do so either. The -rationale is that the various types only serve to distinguish how the value is -**encoded on the wire**; once loaded in memory, the user is not concerned about -these variations. - -Swift’s lack of implicit conversions among types will make it slightly annoying -to use these types in a context expecting an `Int`, or vice-versa, but since -this is a data-interchange format with explicitly-sized fields, we should not -hide that information from the user. Users will have to explicitly write -`Int(message.myField)`, for example. - -## Embedded message fields - -Embedded message fields can be represented using an optional variable of the -generated message type. Thus, the message - -```protobuf -message Foo { - Bar bar = 1; -} -``` - -would be represented in Swift as - -```swift -public struct Foo: ProtoMessage { - public var bar: Bar! { - get { ... } - set { ... } - } -} -``` - -If the user explicitly sets `bar` to nil, or if it was never set when read from -the wire, retrieving the value of `bar` would return a default, statically -allocated instance of `Bar` containing default values for its fields. This -achieves the desired behavior for default values in the same way that scalar -fields are designed, and also allows users to deep-drill into complex object -graphs to get or set fields without checking for nil at each step. - -## Enum fields - -The design and implementation of enum fields will differ somewhat drastically -depending on whether the message being generated is a proto2 or proto3 message. - -### proto2 enums - -For proto2, we do not need to be concerned about unknown enum values, so we can -use the simple raw-value enum syntax provided by Swift. So the following enum in -proto2: - -```protobuf -enum ContentType { - TEXT = 0; - IMAGE = 1; -} -``` - -would become this Swift enum: - -```swift -public enum ContentType: Int32, NilLiteralConvertible { - case text = 0 - case image = 1 - - public init(nilLiteral: ()) { - self = .text - } -} -``` - -See below for the discussion about `NilLiteralConvertible`. - -### proto3 enums - -For proto3, we need to be able to preserve unknown enum values that may come -across the wire so that they can be written back if unmodified. We can -accomplish this in Swift by using a case with an associated value for unknowns. -So the following enum in proto3: - -```protobuf -enum ContentType { - TEXT = 0; - IMAGE = 1; -} -``` - -would become this Swift enum: - -```swift -public enum ContentType: RawRepresentable, NilLiteralConvertible { - case text - case image - case UNKNOWN_VALUE(Int32) - - public typealias RawValue = Int32 - - public init(nilLiteral: ()) { - self = .text - } - - public init(rawValue: RawValue) { - switch rawValue { - case 0: self = .text - case 1: self = .image - default: self = .UNKNOWN_VALUE(rawValue) - } - - public var rawValue: RawValue { - switch self { - case .text: return 0 - case .image: return 1 - case .UNKNOWN_VALUE(let value): return value - } - } -} -``` - -Note that the use of a parameterized case prevents us from inheriting from the -raw `Int32` type; Swift does not allow an enum with a raw type to have cases -with arguments. Instead, we must implement the raw value initializer and -computed property manually. The `UNKNOWN_VALUE` case is explicitly chosen to be -"ugly" so that it stands out and does not conflict with other possible case -names. - -Using this approach, proto3 consumers must always have a default case or handle -the `.UNKNOWN_VALUE` case to satisfy case exhaustion in a switch statement; the -Swift compiler considers it an error if switch statements are not exhaustive. - -### NilLiteralConvertible conformance - -This is required to clean up the usage of enum-typed properties in switch -statements. Unlike other field types, enum properties cannot be -implicitly-unwrapped optionals without requiring that uses in switch statements -be explicitly unwrapped. For example, if we consider a message with the enum -above, this usage will fail to compile: - -```swift -// Without NilLiteralConvertible conformance on ContentType -public struct SomeMessage: ProtoMessage { - public var contentType: ContentType! { ... } -} - -// ERROR: no case named text or image -switch someMessage.contentType { - case .text: { ... } - case .image: { ... } -} -``` - -Even though our implementation guarantees that `contentType` will never be nil, -if it is an optional type, its cases would be `some` and `none`, not the cases -of the underlying enum type. In order to use it in this context, the user must -write `someMessage.contentType!` in their switch statement. - -Making the enum itself `NilLiteralConvertible` permits us to make the property -non-optional, so the user can still set it to nil to clear it (i.e., reset it to -its default value), while eliminating the need to explicitly unwrap it in a -switch statement. - -```swift -// With NilLiteralConvertible conformance on ContentType -public struct SomeMessage: ProtoMessage { - // Note that the property type is no longer optional - public var contentType: ContentType { ... } -} - -// OK: Compiles and runs as expected -switch someMessage.contentType { - case .text: { ... } - case .image: { ... } -} - -// The enum can be reset to its default value this way -someMessage.contentType = nil -``` - -One minor oddity with this approach is that nil will be auto-converted to the -default value of the enum in any context, not just field assignment. In other -words, this is valid: - -```swift -func foo(contentType: ContentType) { ... } -foo(nil) // Inside foo, contentType == .text -``` - -That being said, the advantage of being able to simultaneously support -nil-resettability and switch-without-unwrapping outweighs this side effect, -especially if appropriately documented. It is our hope that a new form of -resettable properties will be added to Swift that eliminates this inconsistency. -Some community members have already drafted or sent proposals for review that -would benefit our designs: - -* [SE-0030: Property Behaviors] - (https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md) -* [Drafted: Resettable Properties] - (https://github.com/patters/swift-evolution/blob/master/proposals/0000-resettable-properties.md) - -### Enum aliases - -The `allow_alias` option in protobuf slightly complicates the use of Swift enums -to represent that type, because raw values of cases in an enum must be unique. -Swift lets us define static variables in an enum that alias actual cases. For -example, the following protobuf enum: - -```protobuf -enum Foo { - option allow_alias = true; - BAR = 0; - BAZ = 0; -} -``` - -will be represented in Swift as: - -```swift -public enum Foo: Int32, NilLiteralConvertible { - case bar = 0 - static public let baz = bar - - // ... etc. -} - -// Can still use .baz shorthand to reference the alias in contexts -// where the type is inferred -``` - -That is, we use the first name as the actual case and use static variables for -the other aliases. One drawback to this approach is that the static aliases -cannot be used as cases in a switch statement (the compiler emits the error -*“Enum case ‘baz’ not found in type ‘Foo’”*). However, in our own code bases, -there are only a few places where enum aliases are not mere renamings of an -older value, but they also don’t appear to be the type of value that one would -expect to switch on (for example, a group of named constants representing -metrics rather than a set of options), so this restriction is not significant. - -This strategy also implies that changing the name of an enum and adding the old -name as an alias below the new name will be a breaking change in the generated -Swift code. - -## Oneof types - -The `oneof` feature represents a “variant/union” data type that maps nicely to -Swift enums with associated values (algebraic types). These fields can also be -accessed independently though, and, specifically in the case of proto2, it’s -reasonable to expect access to default values when accessing a field that is not -explicitly set. - -Taking all this into account, we can represent a `oneof` in Swift with two sets -of constructs: - -* Properties in the message that correspond to the `oneof` fields. -* A nested enum named after the `oneof` and which provides the corresponding - field values as case arguments. - -This approach fulfills the needs of proto consumers by providing a -Swift-idiomatic way of simultaneously checking which field is set and accessing -its value, providing individual properties to access the default values -(important for proto2), and safely allows a field to be moved into a `oneof` -without breaking clients. - -Consider the following proto: - -```protobuf -message MyMessage { - oneof record { - string name = 1 [default = "unnamed"]; - int32 id_number = 2 [default = 0]; - } -} -``` - -In Swift, we would generate an enum, a property for that enum, and properties -for the fields themselves: - -```swift -public struct MyMessage: ProtoMessage { - public enum Record: NilLiteralConvertible { - case name(String) - case idNumber(Int32) - case NOT_SET - - public init(nilLiteral: ()) { self = .NOT_SET } - } - - // This is the "Swifty" way of accessing the value - public var record: Record { ... } - - // Direct access to the underlying fields - public var name: String! { ... } - public var idNumber: Int32! { ... } -} -``` - -This makes both usage patterns possible: - -```swift -// Usage 1: Case-based dispatch -switch message.record { - case .name(let name): - // Do something with name if it was explicitly set - case .idNumber(let id): - // Do something with id_number if it was explicitly set - case .NOT_SET: - // Do something if it’s not set -} - -// Usage 2: Direct access for default value fallback -// Sets the label text to the name if it was explicitly set, or to -// "unnamed" (the default value for the field) if id_number was set -// instead -let myLabel = UILabel() -myLabel.text = message.name -``` - -As with proto enums, the generated `oneof` enum conforms to -`NilLiteralConvertible` to avoid switch statement issues. Setting the property -to nil will clear it (i.e., reset it to `NOT_SET`). - -## Unknown Fields (proto2 only) - -To be written. - -## Extensions (proto2 only) - -To be written. - -## Reflection and Descriptors - -We will not include reflection or descriptors in the first version of the Swift -library. The use cases for reflection on mobile are not as strong and the static -data to represent the descriptors would add bloat when we wish to keep the code -size small. - -In the future, we will investigate whether they can be included as extensions -which might be able to be excluded from a build and/or automatically dead -stripped by the compiler if they are not used. - -## Appendix A: Rejected strategies to handle packages - -### Each package is its own Swift module - -Each proto package could be declared as its own Swift module, replacing dots -with underscores (e.g., package `foo.bar` becomes module `Foo_Bar`). Then, users -would simply import modules containing whatever proto modules they want to use -and refer to the generated types by their short names. - -**This solution is simply not possible, however.** Swift modules cannot -circularly reference each other, but there is no restriction against proto -packages doing so. Circular imports are forbidden (e.g., `foo.proto` importing -`bar.proto` importing `foo.proto`), but nothing prevents package `foo` from -using a type in package `bar` which uses a different type in package `foo`, as -long as there is no import cycle. If these packages were generated as Swift -modules, then `Foo` would contain an `import Bar` statement and `Bar` would -contain an `import Foo` statement, and there is no way to compile this. - -### Ad hoc namespacing with structs - -We can “fake” namespaces in Swift by declaring empty structs with private -initializers. Since modules are constructed based on compiler arguments, not by -syntactic constructs, and because there is no pure Swift way to define -submodules (even though Clang module maps support this), there is no -source-drive way to group generated code into namespaces aside from this -approach. - -Types can be added to those intermediate package structs using Swift extensions. -For example, a message `Baz` in package `foo.bar` could be represented in Swift -as follows: - -```swift -public struct Foo { - private init() {} -} - -public extension Foo { - public struct Bar { - private init() {} - } -} - -public extension Foo.Bar { - public struct Baz { - // Message fields and other methods - } -} - -let baz = Foo.Bar.Baz() -``` - -Each of these constructs would actually be defined in a separate file; Swift -lets us keep them separate and add multiple structs to a single “namespace” -through extensions. - -Unfortunately, these intermediate structs generate symbols of their own -(metatype information in the data segment). This becomes problematic if multiple -build targets contain Swift sources generated from different messages in the -same package. At link time, these symbols would collide, resulting in multiple -definition errors. - -This approach also has the disadvantage that there is no automatic “short” way -to refer to the generated messages at the deepest nesting levels; since this use -of structs is a hack around the lack of namespaces, there is no equivalent to -import (Java) or using (C++) to simplify this. Users would have to declare type -aliases to make this cleaner, or we would have to generate them for users. diff --git a/docs/third_party.md b/docs/third_party.md index 21a79079..8ec551db 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -46,7 +46,6 @@ These are projects we know about implementing Protocol Buffers for other program * Java/Android: https://github.com/square/wire * Java ME: http://code.google.com/p/protobuf-javame/ * Java ME: http://swingme.sourceforge.net/encode.shtml -* Java ME: http://github.com/ponderingpanda/protobuf-j2me * Java ME: http://code.google.com/p/protobuf-j2me/ * Javascript: http://code.google.com/p/protobuf-js/ * Javascript: http://github.com/sirikata/protojs diff --git a/generate_changelog.py b/generate_changelog.py new file mode 100755 index 00000000..d7575d46 --- /dev/null +++ b/generate_changelog.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +"""Generates a friendly list of changes per language since the last release.""" + +import sys +import os + +class Language(object): + def __init__(self, name, pathspec): + self.name = name + self.pathspec = pathspec + +languages = [ + Language("C++", [ + "':(glob)src/google/protobuf/*'", + "src/google/protobuf/compiler/cpp", + "src/google/protobuf/io", + "src/google/protobuf/util", + "src/google/protobuf/stubs", + ]), + Language("Java", [ + "java", + "javanano", + "src/google/protobuf/compiler/cpp", + ]), + Language("Python", [ + "javanano", + "src/google/protobuf/compiler/python", + ]), + Language("JavaScript", [ + "js", + "src/google/protobuf/compiler/js", + ]), + Language("PHP", [ + "php", + "src/google/protobuf/compiler/php", + ]), + Language("Ruby", [ + "ruby", + "src/google/protobuf/compiler/ruby", + ]), + Language("Csharp", [ + "csharp", + "src/google/protobuf/compiler/csharp", + ]), + Language("Objective C", [ + "objectivec", + "src/google/protobuf/compiler/objectivec", + ]), +] + +if len(sys.argv) < 2: + print("Usage: generate_changelog.py <previous release>") + sys.exit(1) + +previous = sys.argv[1] + +for language in languages: + print(language.name) + os.system(("git log --pretty=oneline --abbrev-commit %s...HEAD %s | " + + "sed -e 's/^/ - /'") % (previous, " ".join(language.pathspec))) + print("") + +print("To view a commit on GitHub: " + + "https://github.com/google/protobuf/commit/<commit id>") diff --git a/jenkins/build_and_run_docker.sh b/jenkins/build_and_run_docker.sh index abc6f055..50e1e8c6 100755 --- a/jenkins/build_and_run_docker.sh +++ b/jenkins/build_and_run_docker.sh @@ -33,6 +33,7 @@ docker run \ "$@" \ -e CCACHE_DIR=$CCACHE_DIR \ -e EXTERNAL_GIT_ROOT="/var/local/jenkins/protobuf" \ + -e TEST_SET="$TEST_SET" \ -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \ -v "$git_root:/var/local/jenkins/protobuf:ro" \ -v $CCACHE_DIR:$CCACHE_DIR \ diff --git a/jenkins/buildcmds/pull_request.sh b/jenkins/buildcmds/pull_request.sh index 01fda798..51e4bfa4 100755 --- a/jenkins/buildcmds/pull_request.sh +++ b/jenkins/buildcmds/pull_request.sh @@ -12,4 +12,5 @@ export DOCKERFILE_DIR=jenkins/docker export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh export OUTPUT_DIR=testoutput +export TEST_SET="csharp java_jdk7 javanano_jdk7 java_oracle7 javanano_oracle7 python python_cpp ruby_all javascript golang php_all" ./jenkins/build_and_run_docker.sh diff --git a/jenkins/buildcmds/pull_request_32.sh b/jenkins/buildcmds/pull_request_32.sh new file mode 100755 index 00000000..99df2971 --- /dev/null +++ b/jenkins/buildcmds/pull_request_32.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# This is the top-level script we give to Jenkins as the entry point for +# running the "pull request 32" project: +# +# https://grpc-testing.appspot.com/view/Protocol%20Buffers/job/Protocol%20Buffers%20Pull%20Request%2032/ +# +# This script selects a specific Dockerfile (for building a Docker image) and +# a script to run inside that image. Then we delegate to the general +# build_and_run_docker.sh script. + +export DOCKERFILE_DIR=jenkins/docker32 +export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="php_all" +./jenkins/build_and_run_docker.sh diff --git a/jenkins/docker/Dockerfile b/jenkins/docker/Dockerfile index 4bfbef34..df3dc8c2 100644 --- a/jenkins/docker/Dockerfile +++ b/jenkins/docker/Dockerfile @@ -75,6 +75,8 @@ RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ python3.4-dev \ # -- For Ruby -- ruby \ + # -- For C++ benchmarks -- + cmake \ # -- For PHP -- php5.5 \ php5.5-dev \ diff --git a/jenkins/docker32/Dockerfile b/jenkins/docker32/Dockerfile new file mode 100644 index 00000000..73dfd8d5 --- /dev/null +++ b/jenkins/docker32/Dockerfile @@ -0,0 +1,108 @@ +# This Dockerfile specifies the recipe for creating an image for the tests +# to run in. +# +# We install as many test dependencies here as we can, because these setup +# steps can be cached. They do *not* run every time we run the build. +# The Docker image is only rebuilt when the Dockerfile (ie. this file) +# changes. + +# Base Dockerfile for gRPC dev images +FROM 32bit/debian:latest + +# Apt source for php +RUN echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu trusty main" | tee /etc/apt/sources.list.d/various-php.list && \ + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F4FCBB07 + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + unzip \ + # -- For python -- + python-setuptools \ + python-pip \ + python-dev \ + # -- For C++ benchmarks -- + cmake \ + # -- For PHP -- + php5.5 \ + php5.5-dev \ + php5.5-xml \ + php5.6 \ + php5.6-dev \ + php5.6-xml \ + php7.0 \ + php7.0-dev \ + php7.0-xml \ + phpunit \ + valgrind \ + libxml2-dev \ + && apt-get clean + +################## +# PHP dependencies. +RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +RUN php composer-setup.php +RUN mv composer.phar /usr/bin/composer +RUN php -r "unlink('composer-setup.php');" +RUN cd /tmp && \ + git clone https://github.com/google/protobuf.git && \ + cd protobuf && \ + ln -sfn /usr/bin/php5.5 /usr/bin/php && \ + ln -sfn /usr/bin/php-config5.5 /usr/bin/php-config && \ + ln -sfn /usr/bin/phpize5.5 /usr/bin/phpize && \ + composer install && \ + mv vendor /usr/local/vendor-5.5 && \ + ln -sfn /usr/bin/php5.6 /usr/bin/php && \ + ln -sfn /usr/bin/php-config5.6 /usr/bin/php-config && \ + ln -sfn /usr/bin/phpize5.6 /usr/bin/phpize && \ + composer install && \ + mv vendor /usr/local/vendor-5.6 && \ + ln -sfn /usr/bin/php7.0 /usr/bin/php && \ + ln -sfn /usr/bin/php-config7.0 /usr/bin/php-config && \ + ln -sfn /usr/bin/phpize7.0 /usr/bin/phpize && \ + composer install && \ + mv vendor /usr/local/vendor-7.0 +RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror +RUN mv mirror php-5.5.38.tar.bz2 +RUN tar -xvf php-5.5.38.tar.bz2 +RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \ + make && make install + +################## +# Python dependencies + +# These packages exist in apt-get, but their versions are too old, so we have +# to get updates from pip. + +RUN pip install pip --upgrade +RUN pip install virtualenv tox yattag + +################## +# Prepare ccache + +RUN ln -s /usr/bin/ccache /usr/local/bin/gcc +RUN ln -s /usr/bin/ccache /usr/local/bin/g++ +RUN ln -s /usr/bin/ccache /usr/local/bin/cc +RUN ln -s /usr/bin/ccache /usr/local/bin/c++ +RUN ln -s /usr/bin/ccache /usr/local/bin/clang +RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ + +# Define the default command. +CMD ["bash"] diff --git a/jenkins/pull_request_in_docker.sh b/jenkins/pull_request_in_docker.sh index b843a355..10daf0a5 100755 --- a/jenkins/pull_request_in_docker.sh +++ b/jenkins/pull_request_in_docker.sh @@ -45,20 +45,11 @@ TIME_CMD="/usr/bin/time -f %e -o $LOG_OUTPUT_DIR/1/cpp/build_time" $TIME_CMD $TEST_SCRIPT cpp > >(tee $CPP_STDOUT) 2> >(tee $CPP_STDERR >&2) -# Other tests are run in parallel. +# Other tests are run in parallel. TEST_SET is defined in +# buildcmds/pull_request{_32}.sh parallel --results $LOG_OUTPUT_DIR --joblog $OUTPUT_DIR/joblog $TEST_SCRIPT ::: \ - csharp \ - java_jdk7 \ - javanano_jdk7 \ - java_oracle7 \ - javanano_oracle7 \ - python \ - python_cpp \ - ruby_all \ - javascript \ - golang \ - php_all \ + $TEST_SET \ || true # Process test results even if tests fail. cat $OUTPUT_DIR/joblog diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 89240ee0..7b335618 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -228,34 +228,23 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then # NOTE: Different Xcode have different simulated hardware/os support. readonly XCODE_VERSION_LINE="$(xcodebuild -version | grep Xcode\ )" readonly XCODE_VERSION="${XCODE_VERSION_LINE/Xcode /}" # drop the prefix. - IOS_SIMULATOR_NAME="Simulator" case "${XCODE_VERSION}" in 6.* ) - echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 7.0 or higher." 1>&2 + echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 8.0 or higher." 1>&2 exit 10 ;; - 7.1* ) - XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPhone 6,OS=9.0" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPad Air,OS=9.0" # 64bit - ) + 7.* ) + echo "ERROR: The unittests include Swift code that is now Swift 3.0." 1>&2 + echo "ERROR: Xcode 8.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2 + exit 11 ;; - 7.2* ) + 8.0* ) + # The 8.* device seem to hang and never start under Xcode 8. XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPhone 6,OS=9.2" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPad Air,OS=9.2" # 64bit - ) - ;; - 7.3* ) - XCODEBUILD_TEST_BASE_IOS+=( - -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPhone 6,OS=9.3" # 64bit - -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit - -destination "platform=iOS Simulator,name=iPad Air,OS=9.3" # 64bit + -destination "platform=iOS Simulator,name=iPhone 4s,OS=9.0" # 32bit + -destination "platform=iOS Simulator,name=iPhone 7,OS=10.0" # 64bit + -destination "platform=iOS Simulator,name=iPad 2,OS=9.0" # 32bit + -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.0" # 64bit ) ;; * ) @@ -272,7 +261,7 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Release test fi # Don't leave the simulator in the developer's face. - killall "${IOS_SIMULATOR_NAME}" + killall Simulator fi if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then XCODEBUILD_TEST_BASE_OSX=( @@ -282,6 +271,19 @@ if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then # Since the ObjC 2.0 Runtime is required, 32bit OS X isn't supported. -destination "platform=OS X,arch=x86_64" # 64bit ) + readonly XCODE_VERSION_LINE="$(xcodebuild -version | grep Xcode\ )" + readonly XCODE_VERSION="${XCODE_VERSION_LINE/Xcode /}" # drop the prefix. + case "${XCODE_VERSION}" in + 6.* ) + echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 8.0 or higher." 1>&2 + exit 10 + ;; + 7.* ) + echo "ERROR: The unittests include Swift code that is now Swift 3.0." 1>&2 + echo "ERROR: Xcode 8.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2 + exit 11 + ;; + esac if [[ "${DO_XCODE_DEBUG}" == "yes" ]] ; then header "Doing Xcode OS X build/tests - Debug" "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Debug test diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index 1585dbed..7ce5d54f 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -556,9 +556,10 @@ attributes = { LastSwiftUpdateCheck = 0710; LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0800; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { + LastSwiftMigration = 0800; TestTargetID = 8B9A5EA41831993600A9D33B; }; F45BBC141B0CE3C6002D064D = { @@ -740,6 +741,7 @@ PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; WARNING_CFLAGS = ( "$(inherited)", "-Wno-documentation-unknown-command", @@ -764,6 +766,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; + SWIFT_VERSION = 3.0; WARNING_CFLAGS = ( "$(inherited)", "-Wno-documentation-unknown-command", @@ -785,16 +788,21 @@ CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; @@ -846,16 +854,21 @@ CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -881,6 +894,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.9; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; WARNING_CFLAGS = ( "-Wdocumentation-unknown-command", "-Wundef", diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 25814c5f..2f618131 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0710" + LastUpgradeVersion = "0800" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index 3eb4f92b..b1243b79 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0710" + LastUpgradeVersion = "0800" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index b6bc95ab..5f599719 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -633,9 +633,10 @@ attributes = { LastSwiftUpdateCheck = 0710; LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0800; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { + LastSwiftMigration = 0800; TestTargetID = 8B9A5EA41831993600A9D33B; }; F45BBC0E1B0CDB50002D064D = { @@ -843,7 +844,7 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CLANG_ENABLE_OBJC_ARC = YES; INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -858,7 +859,7 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CLANG_ENABLE_OBJC_ARC = YES; INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; PRODUCT_BUNDLE_IDENTIFIER = "com.google.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -880,7 +881,7 @@ "$(SRCROOT)", ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -890,6 +891,7 @@ PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestHarness.app/iOSTestHarness"; WARNING_CFLAGS = ( @@ -915,7 +917,7 @@ "$(SRCROOT)", ); INFOPLIST_FILE = "Tests/UnitTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -924,6 +926,7 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = UnitTests; SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestHarness.app/iOSTestHarness"; WARNING_CFLAGS = ( @@ -947,17 +950,22 @@ CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; @@ -982,7 +990,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; GENERATE_PROFILING_CODE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 6.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; @@ -1009,17 +1017,22 @@ CLANG_WARN_ASSIGN_ENUM = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION = YES; CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -1042,9 +1055,10 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; GENERATE_PROFILING_CODE = NO; - IPHONEOS_DEPLOYMENT_TARGET = 6.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; WARNING_CFLAGS = ( "-Wdocumentation-unknown-command", "-Wundef", diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 0b96b75f..be31c308 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0710" + LastUpgradeVersion = "0800" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index d53a75f9..edbe6898 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "0710" + LastUpgradeVersion = "0800" version = "1.3"> <BuildAction parallelizeBuildables = "YES" diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift index b5999c21..9d8a0fae 100644 --- a/objectivec/Tests/GPBSwiftTests.swift +++ b/objectivec/Tests/GPBSwiftTests.swift @@ -42,23 +42,23 @@ class GPBBridgeTests: XCTestCase { msg.optionalInt32 = 100 msg.optionalString = "abc" - msg.optionalEnum = .Bar + msg.optionalEnum = .bar msg2.optionalString = "other" - msg.optionalMessage = msg2 + msg.optional = msg2 msg3.a = 200 msg.optionalGroup = msg3 msg.repeatedInt32Array.addValue(300) msg.repeatedInt32Array.addValue(301) - msg.repeatedStringArray.addObject("mno") - msg.repeatedStringArray.addObject("pqr") - msg.repeatedEnumArray.addValue(Message2_Enum.Bar.rawValue) - msg.repeatedEnumArray.addValue(Message2_Enum.Baz.rawValue) + msg.repeatedStringArray.add("mno") + msg.repeatedStringArray.add("pqr") + msg.repeatedEnumArray.addValue(Message2_Enum.bar.rawValue) + msg.repeatedEnumArray.addValue(Message2_Enum.baz.rawValue) msg.mapInt32Int32.setInt32(400, forKey:500) msg.mapInt32Int32.setInt32(401, forKey:501) - msg.mapStringString.setObject("foo", forKey:"bar") - msg.mapStringString.setObject("abc", forKey:"xyz") - msg.mapInt32Enum.setEnum(Message2_Enum.Bar.rawValue, forKey:600) - msg.mapInt32Enum.setEnum(Message2_Enum.Baz.rawValue, forKey:601) + msg.mapStringString.setObject("foo", forKey:"bar" as NSString) + msg.mapStringString.setObject("abc", forKey:"xyz" as NSString) + msg.mapInt32Enum.setEnum(Message2_Enum.bar.rawValue, forKey:600) + msg.mapInt32Enum.setEnum(Message2_Enum.baz.rawValue, forKey:601) // Check has*. XCTAssertTrue(msg.hasOptionalInt32) @@ -75,19 +75,19 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.optionalInt32, Int32(100)) XCTAssertEqual(msg.optionalString, "abc") XCTAssertEqual(msg2.optionalString, "other") - XCTAssertTrue(msg.optionalMessage === msg2) - XCTAssertEqual(msg.optionalEnum, Message2_Enum.Bar) + XCTAssertTrue(msg.optional === msg2) + XCTAssertEqual(msg.optionalEnum, Message2_Enum.bar) XCTAssertEqual(msg3.a, Int32(200)) XCTAssertTrue(msg.optionalGroup === msg3) XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2)) - XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300)) - XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301)) + XCTAssertEqual(msg.repeatedInt32Array.value(at: 0), Int32(300)) + XCTAssertEqual(msg.repeatedInt32Array.value(at: 1), Int32(301)) XCTAssertEqual(msg.repeatedStringArray.count, Int(2)) - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as? String, "mno") - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as? String, "pqr") + XCTAssertEqual(msg.repeatedStringArray.object(at: 0) as? String, "mno") + XCTAssertEqual(msg.repeatedStringArray.object(at: 1) as? String, "pqr") XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2)) - XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message2_Enum.Bar.rawValue) - XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message2_Enum.Baz.rawValue) + XCTAssertEqual(msg.repeatedEnumArray.value(at: 0), Message2_Enum.bar.rawValue) + XCTAssertEqual(msg.repeatedEnumArray.value(at: 1), Message2_Enum.baz.rawValue) XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0)) XCTAssertEqual(msg.mapInt32Int32.count, UInt(2)) var intValue: Int32 = 0 @@ -96,13 +96,13 @@ class GPBBridgeTests: XCTestCase { XCTAssertTrue(msg.mapInt32Int32.getInt32(&intValue, forKey: 501)) XCTAssertEqual(intValue, Int32(401)) XCTAssertEqual(msg.mapStringString.count, Int(2)) - XCTAssertEqual(msg.mapStringString.objectForKey("bar") as? String, "foo") - XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as? String, "abc") + XCTAssertEqual(msg.mapStringString.object(forKey: "bar") as? String, "foo") + XCTAssertEqual(msg.mapStringString.object(forKey: "xyz") as? String, "abc") XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:600)) - XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue) + XCTAssertEqual(intValue, Message2_Enum.bar.rawValue) XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:601)) - XCTAssertEqual(intValue, Message2_Enum.Baz.rawValue) + XCTAssertEqual(intValue, Message2_Enum.baz.rawValue) // Clearing a string with nil. msg2.optionalString = nil @@ -124,8 +124,8 @@ class GPBBridgeTests: XCTestCase { XCTAssertFalse(msg.hasOptionalFloat) XCTAssertEqual(msg.optionalInt32, Int32(0)) XCTAssertEqual(msg.optionalString, "") - XCTAssertTrue(msg.optionalMessage !== msg2) // New instance - XCTAssertEqual(msg.optionalEnum, Message2_Enum.Foo) // Default + XCTAssertTrue(msg.optional !== msg2) // New instance + XCTAssertEqual(msg.optionalEnum, Message2_Enum.foo) // Default XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0)) XCTAssertEqual(msg.repeatedStringArray.count, Int(0)) XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0)) @@ -140,22 +140,22 @@ class GPBBridgeTests: XCTestCase { msg.optionalInt32 = 100 msg.optionalString = "abc" - msg.optionalEnum = .Bar + msg.optionalEnum = .bar msg2.optionalString = "other" - msg.optionalMessage = msg2 + msg.optional = msg2 msg.repeatedInt32Array.addValue(300) msg.repeatedInt32Array.addValue(301) - msg.repeatedStringArray.addObject("mno") - msg.repeatedStringArray.addObject("pqr") + msg.repeatedStringArray.add("mno") + msg.repeatedStringArray.add("pqr") // "proto3" syntax lets enum get unknown values. - msg.repeatedEnumArray.addValue(Message3_Enum.Bar.rawValue) + msg.repeatedEnumArray.addValue(Message3_Enum.bar.rawValue) msg.repeatedEnumArray.addRawValue(666) SetMessage3_OptionalEnum_RawValue(msg2, 666) msg.mapInt32Int32.setInt32(400, forKey:500) msg.mapInt32Int32.setInt32(401, forKey:501) - msg.mapStringString.setObject("foo", forKey:"bar") - msg.mapStringString.setObject("abc", forKey:"xyz") - msg.mapInt32Enum.setEnum(Message2_Enum.Bar.rawValue, forKey:600) + msg.mapStringString.setObject("foo", forKey:"bar" as NSString) + msg.mapStringString.setObject("abc", forKey:"xyz" as NSString) + msg.mapInt32Enum.setEnum(Message2_Enum.bar.rawValue, forKey:600) // "proto3" syntax lets enum get unknown values. msg.mapInt32Enum.setRawValue(666, forKey:601) @@ -167,20 +167,20 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.optionalInt32, Int32(100)) XCTAssertEqual(msg.optionalString, "abc") XCTAssertEqual(msg2.optionalString, "other") - XCTAssertTrue(msg.optionalMessage === msg2) - XCTAssertEqual(msg.optionalEnum, Message3_Enum.Bar) + XCTAssertTrue(msg.optional === msg2) + XCTAssertEqual(msg.optionalEnum, Message3_Enum.bar) XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2)) - XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300)) - XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301)) + XCTAssertEqual(msg.repeatedInt32Array.value(at: 0), Int32(300)) + XCTAssertEqual(msg.repeatedInt32Array.value(at: 1), Int32(301)) XCTAssertEqual(msg.repeatedStringArray.count, Int(2)) - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as? String, "mno") - XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as? String, "pqr") + XCTAssertEqual(msg.repeatedStringArray.object(at: 0) as? String, "mno") + XCTAssertEqual(msg.repeatedStringArray.object(at: 1) as? String, "pqr") XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0)) XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2)) - XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message3_Enum.Bar.rawValue) - XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message3_Enum.GPBUnrecognizedEnumeratorValue.rawValue) - XCTAssertEqual(msg.repeatedEnumArray.rawValueAtIndex(1), 666) - XCTAssertEqual(msg2.optionalEnum, Message3_Enum.GPBUnrecognizedEnumeratorValue) + XCTAssertEqual(msg.repeatedEnumArray.value(at: 0), Message3_Enum.bar.rawValue) + XCTAssertEqual(msg.repeatedEnumArray.value(at: 1), Message3_Enum.gpbUnrecognizedEnumeratorValue.rawValue) + XCTAssertEqual(msg.repeatedEnumArray.rawValue(at: 1), 666) + XCTAssertEqual(msg2.optionalEnum, Message3_Enum.gpbUnrecognizedEnumeratorValue) XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Int32(666)) XCTAssertEqual(msg.mapInt32Int32.count, UInt(2)) var intValue: Int32 = 0 @@ -189,13 +189,13 @@ class GPBBridgeTests: XCTestCase { XCTAssertTrue(msg.mapInt32Int32.getInt32(&intValue, forKey:501)) XCTAssertEqual(intValue, Int32(401)) XCTAssertEqual(msg.mapStringString.count, Int(2)) - XCTAssertEqual(msg.mapStringString.objectForKey("bar") as? String, "foo") - XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as? String, "abc") + XCTAssertEqual(msg.mapStringString.object(forKey: "bar") as? String, "foo") + XCTAssertEqual(msg.mapStringString.object(forKey: "xyz") as? String, "abc") XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:600)) - XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue) + XCTAssertEqual(intValue, Message2_Enum.bar.rawValue) XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:601)) - XCTAssertEqual(intValue, Message3_Enum.GPBUnrecognizedEnumeratorValue.rawValue) + XCTAssertEqual(intValue, Message3_Enum.gpbUnrecognizedEnumeratorValue.rawValue) XCTAssertTrue(msg.mapInt32Enum.getRawValue(&intValue, forKey:601)) XCTAssertEqual(intValue, 666) @@ -204,23 +204,23 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg2.optionalString, "") // Clearing a message with nil. - msg.optionalMessage = nil + msg.optional = nil XCTAssertFalse(msg.hasOptionalMessage) - XCTAssertTrue(msg.optionalMessage !== msg2) // New instance + XCTAssertTrue(msg.optional !== msg2) // New instance // Clear. msg.clear() XCTAssertFalse(msg.hasOptionalMessage) XCTAssertEqual(msg.optionalInt32, Int32(0)) XCTAssertEqual(msg.optionalString, "") - XCTAssertTrue(msg.optionalMessage !== msg2) // New instance - XCTAssertEqual(msg.optionalEnum, Message3_Enum.Foo) // Default + XCTAssertTrue(msg.optional !== msg2) // New instance + XCTAssertEqual(msg.optionalEnum, Message3_Enum.foo) // Default XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0)) XCTAssertEqual(msg.repeatedStringArray.count, Int(0)) XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0)) msg2.clear() - XCTAssertEqual(msg2.optionalEnum, Message3_Enum.Foo) // Default - XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Message3_Enum.Foo.rawValue) + XCTAssertEqual(msg2.optionalEnum, Message3_Enum.foo) // Default + XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Message3_Enum.foo.rawValue) XCTAssertEqual(msg.mapInt32Int32.count, UInt(0)) XCTAssertEqual(msg.mapStringString.count, Int(0)) XCTAssertEqual(msg.mapInt32Enum.count, UInt(0)) @@ -234,201 +234,201 @@ class GPBBridgeTests: XCTestCase { // Access shouldn't result in has* but should return objects. let msg2 = msg.optionalGroup - let msg3 = msg.optionalMessage.optionalMessage - let msg4 = msg.optionalMessage + let msg3 = msg.optional.optional + let msg4 = msg.optional XCTAssertNotNil(msg2) XCTAssertNotNil(msg3) XCTAssertFalse(msg.hasOptionalGroup) - XCTAssertFalse(msg.optionalMessage.hasOptionalMessage) + XCTAssertFalse(msg.optional.hasOptionalMessage) XCTAssertFalse(msg.hasOptionalMessage) // Setting things should trigger has* getting set. msg.optionalGroup.a = 10 - msg.optionalMessage.optionalMessage.optionalInt32 = 100 + msg.optional.optional.optionalInt32 = 100 XCTAssertTrue(msg.hasOptionalGroup) - XCTAssertTrue(msg.optionalMessage.hasOptionalMessage) + XCTAssertTrue(msg.optional.hasOptionalMessage) XCTAssertTrue(msg.hasOptionalMessage) // And they should be the same pointer as before. XCTAssertTrue(msg2 === msg.optionalGroup) - XCTAssertTrue(msg3 === msg.optionalMessage.optionalMessage) - XCTAssertTrue(msg4 === msg.optionalMessage) + XCTAssertTrue(msg3 === msg.optional.optional) + XCTAssertTrue(msg4 === msg.optional) // Clear gets us new objects next time around. msg.clear() XCTAssertFalse(msg.hasOptionalGroup) - XCTAssertFalse(msg.optionalMessage.hasOptionalMessage) + XCTAssertFalse(msg.optional.hasOptionalMessage) XCTAssertFalse(msg.hasOptionalMessage) msg.optionalGroup.a = 20 - msg.optionalMessage.optionalMessage.optionalInt32 = 200 + msg.optional.optional.optionalInt32 = 200 XCTAssertTrue(msg.hasOptionalGroup) - XCTAssertTrue(msg.optionalMessage.hasOptionalMessage) + XCTAssertTrue(msg.optional.hasOptionalMessage) XCTAssertTrue(msg.hasOptionalMessage) XCTAssertTrue(msg2 !== msg.optionalGroup) - XCTAssertTrue(msg3 !== msg.optionalMessage.optionalMessage) - XCTAssertTrue(msg4 !== msg.optionalMessage) + XCTAssertTrue(msg3 !== msg.optional.optional) + XCTAssertTrue(msg4 !== msg.optional) // Explicit set of a message, means autocreated object doesn't bind. msg.clear() - let autoCreated = msg.optionalMessage + let autoCreated = msg.optional XCTAssertFalse(msg.hasOptionalMessage) let msg5 = Message2() msg5.optionalInt32 = 123 - msg.optionalMessage = msg5 + msg.optional = msg5 XCTAssertTrue(msg.hasOptionalMessage) // Modifing the autocreated doesn't replaced the explicit set one. - autoCreated.optionalInt32 = 456 + autoCreated?.optionalInt32 = 456 XCTAssertTrue(msg.hasOptionalMessage) - XCTAssertTrue(msg.optionalMessage === msg5) - XCTAssertEqual(msg.optionalMessage.optionalInt32, Int32(123)) + XCTAssertTrue(msg.optional === msg5) + XCTAssertEqual(msg.optional.optionalInt32, Int32(123)) } func testProto2OneOfSupport() { let msg = Message2() - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase) XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default - let autoCreated = msg.oneofMessage // Default create one. + XCTAssertEqual(msg.oneofEnum, Message2_Enum.baz) // Default + let autoCreated = msg.oneof // Default create one. XCTAssertNotNil(autoCreated) - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase) msg.oneofInt32 = 10 XCTAssertEqual(msg.oneofInt32, Int32(10)) XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32) + XCTAssertEqual(msg.oneofEnum, Message2_Enum.baz) // Default + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.oneofInt32) msg.oneofFloat = 20.0 XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default XCTAssertEqual(msg.oneofFloat, Float(20.0)) - XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofFloat) + XCTAssertEqual(msg.oneofEnum, Message2_Enum.baz) // Default + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.oneofFloat) - msg.oneofEnum = .Bar + msg.oneofEnum = .bar XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message2_Enum.Bar) - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofEnum) + XCTAssertEqual(msg.oneofEnum, Message2_Enum.bar) + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.oneofEnum) // Sets via the autocreated instance. - msg.oneofMessage.optionalInt32 = 200 + msg.oneof.optionalInt32 = 200 XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200)) - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage) + XCTAssertEqual(msg.oneofEnum, Message2_Enum.baz) // Default + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oneof.optionalInt32, Int32(200)) + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.oneofMessage) // Clear the oneof. Message2_ClearOOneOfCase(msg) XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default - let autoCreated2 = msg.oneofMessage // Default create one + XCTAssertEqual(msg.oneofEnum, Message2_Enum.baz) // Default + let autoCreated2 = msg.oneof // Default create one XCTAssertNotNil(autoCreated2) XCTAssertTrue(autoCreated2 !== autoCreated) // New instance - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oneof.optionalInt32, Int32(0)) // Default + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase) msg.oneofInt32 = 10 XCTAssertEqual(msg.oneofInt32, Int32(10)) - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32) + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.oneofInt32) // Confirm Message.clear() handles the oneof correctly. msg.clear() XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase) // Sets via the autocreated instance. - msg.oneofMessage.optionalInt32 = 300 - XCTAssertTrue(msg.oneofMessage !== autoCreated) // New instance - XCTAssertTrue(msg.oneofMessage !== autoCreated2) // New instance - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300)) - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage) + msg.oneof.optionalInt32 = 300 + XCTAssertTrue(msg.oneof !== autoCreated) // New instance + XCTAssertTrue(msg.oneof !== autoCreated2) // New instance + XCTAssertEqual(msg.oneof.optionalInt32, Int32(300)) + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.oneofMessage) // Set message to nil clears the oneof. - msg.oneofMessage = nil - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default - XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase) + msg.oneof = nil + XCTAssertEqual(msg.oneof.optionalInt32, Int32(0)) // Default + XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.gpbUnsetOneOfCase) } func testProto3OneOfSupport() { let msg = Message3() - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.gpbUnsetOneOfCase) XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default - let autoCreated = msg.oneofMessage // Default create one. + XCTAssertEqual(msg.oneofEnum, Message3_Enum.foo) // Default + let autoCreated = msg.oneof // Default create one. XCTAssertNotNil(autoCreated) - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.gpbUnsetOneOfCase) msg.oneofInt32 = 10 XCTAssertEqual(msg.oneofInt32, Int32(10)) XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32) + XCTAssertEqual(msg.oneofEnum, Message3_Enum.foo) // Default + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.oneofInt32) msg.oneofFloat = 20.0 XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default XCTAssertEqual(msg.oneofFloat, Float(20.0)) - XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofFloat) + XCTAssertEqual(msg.oneofEnum, Message3_Enum.foo) // Default + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.oneofFloat) - msg.oneofEnum = .Bar + msg.oneofEnum = .bar XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message3_Enum.Bar) - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofEnum) + XCTAssertEqual(msg.oneofEnum, Message3_Enum.bar) + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.oneofEnum) // Sets via the autocreated instance. - msg.oneofMessage.optionalInt32 = 200 + msg.oneof.optionalInt32 = 200 XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default - XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200)) - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage) + XCTAssertEqual(msg.oneofEnum, Message3_Enum.foo) // Default + XCTAssertTrue(msg.oneof === autoCreated) // Still the same + XCTAssertEqual(msg.oneof.optionalInt32, Int32(200)) + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.oneofMessage) // Clear the oneof. Message3_ClearOOneOfCase(msg) XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default - XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default - let autoCreated2 = msg.oneofMessage // Default create one + XCTAssertEqual(msg.oneofEnum, Message3_Enum.foo) // Default + let autoCreated2 = msg.oneof // Default create one XCTAssertNotNil(autoCreated2) XCTAssertTrue(autoCreated2 !== autoCreated) // New instance - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oneof.optionalInt32, Int32(0)) // Default + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.gpbUnsetOneOfCase) msg.oneofInt32 = 10 XCTAssertEqual(msg.oneofInt32, Int32(10)) - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32) + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.oneofInt32) // Confirm Message.clear() handles the oneof correctly. msg.clear() XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase) + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.gpbUnsetOneOfCase) // Sets via the autocreated instance. - msg.oneofMessage.optionalInt32 = 300 - XCTAssertTrue(msg.oneofMessage !== autoCreated) // New instance - XCTAssertTrue(msg.oneofMessage !== autoCreated2) // New instance - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300)) - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage) + msg.oneof.optionalInt32 = 300 + XCTAssertTrue(msg.oneof !== autoCreated) // New instance + XCTAssertTrue(msg.oneof !== autoCreated2) // New instance + XCTAssertEqual(msg.oneof.optionalInt32, Int32(300)) + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.oneofMessage) // Set message to nil clears the oneof. - msg.oneofMessage = nil - XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default - XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase) + msg.oneof = nil + XCTAssertEqual(msg.oneof.optionalInt32, Int32(0)) // Default + XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.gpbUnsetOneOfCase) } func testSerialization() { @@ -437,12 +437,12 @@ class GPBBridgeTests: XCTestCase { msg.optionalInt32 = 100 msg.optionalInt64 = 101 msg.optionalGroup.a = 102 - msg.repeatedStringArray.addObject("abc") - msg.repeatedStringArray.addObject("def") + msg.repeatedStringArray.add("abc") + msg.repeatedStringArray.add("def") msg.mapInt32Int32.setInt32(200, forKey:300) msg.mapInt32Int32.setInt32(201, forKey:201) - msg.mapStringString.setObject("foo", forKey:"bar") - msg.mapStringString.setObject("abc", forKey:"xyz") + msg.mapStringString.setObject("foo", forKey:"bar" as NSString) + msg.mapStringString.setObject("abc", forKey:"xyz" as NSString) let data = msg.data() diff --git a/protobuf.bzl b/protobuf.bzl index e356f53c..e56a5365 100644 --- a/protobuf.bzl +++ b/protobuf.bzl @@ -62,6 +62,7 @@ def _proto_gen_impl(ctx): if ctx.attr.gen_py: args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir] + inputs = srcs + deps if ctx.executable.plugin: plugin = ctx.executable.plugin lang = ctx.attr.plugin_language @@ -75,10 +76,11 @@ def _proto_gen_impl(ctx): outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir args += ["--plugin=protoc-gen-%s=%s" % (lang, plugin.path)] args += ["--%s_out=%s" % (lang, outdir)] + inputs += [plugin] if args: ctx.action( - inputs=srcs + deps, + inputs=inputs, outputs=ctx.outputs.outs, arguments=args + import_flags + [s.path for s in srcs], executable=ctx.executable.protoc, diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock deleted file mode 100644 index 46244fdf..00000000 --- a/ruby/Gemfile.lock +++ /dev/null @@ -1,30 +0,0 @@ -PATH - remote: . - specs: - google-protobuf (3.1.0) - -GEM - remote: https://rubygems.org/ - specs: - power_assert (0.2.2) - rake (10.4.2) - rake-compiler (0.9.5) - rake - rake-compiler-dock (0.5.1) - rubygems-tasks (0.2.4) - test-unit (3.0.9) - power_assert - -PLATFORMS - java - ruby - -DEPENDENCIES - google-protobuf! - rake-compiler - rake-compiler-dock - rubygems-tasks - test-unit - -BUNDLED WITH - 1.11.2 diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index c7357f78..19be14e5 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -10,16 +10,17 @@ Gem::Specification.new do |s| s.require_paths = ["lib"] s.files = Dir.glob('lib/**/*.rb') if RUBY_PLATFORM == "java" + s.platform = "java" s.files += ["lib/google/protobuf_java.jar"] else s.files += Dir.glob('ext/**/*') s.extensions= ["ext/google/protobuf_c/extconf.rb"] - s.add_development_dependency "rake-compiler-dock" + s.add_development_dependency "rake-compiler-dock", "~> 0.5.1" end s.test_files = ["tests/basic.rb", "tests/stress.rb", "tests/generated_code_test.rb"] - s.add_development_dependency "rake-compiler" - s.add_development_dependency "test-unit" - s.add_development_dependency "rubygems-tasks" + s.add_development_dependency "rake-compiler", "~> 0.9.5" + s.add_development_dependency "test-unit", "~> 3.0.9" + s.add_development_dependency "rubygems-tasks", "~> 0.2.4" end diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 519ed8fc..09c7a2b6 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -570,6 +570,7 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { input_ = NULL; source_code_info_ = NULL; + assert(file != NULL); source_code_info.Swap(file->mutable_source_code_info()); return !had_errors_; } diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc index c9d95899..7194a5b1 100644 --- a/src/google/protobuf/stubs/substitute.cc +++ b/src/google/protobuf/stubs/substitute.cc @@ -113,7 +113,9 @@ void SubstituteAndAppend( for (int i = 0; format[i] != '\0'; i++) { if (format[i] == '$') { if (ascii_isdigit(format[i+1])) { - const SubstituteArg* src = args_array[format[i+1] - '0']; + unsigned int index = format[i+1] - '0'; + assert(index < 10); + const SubstituteArg* src = args_array[index]; memcpy(target, src->data(), src->size()); target += src->size(); ++i; // Skip next char. diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 3013e12f..ac1ed9ab 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -589,7 +589,6 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, new Node(name.ToString(), NULL, PRIMITIVE, data, false, child == NULL ? current_->path() : child->path(), suppress_empty_list_, field_scrub_callback_.get())); - child = node.get(); current_->AddChild(node.release()); } else { child->set_data(data); diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc index fc61dfc3..a8d48eff 100644 --- a/src/google/protobuf/util/internal/json_stream_parser.cc +++ b/src/google/protobuf/util/internal/json_stream_parser.cc @@ -320,7 +320,6 @@ util::Status JsonStreamParser::ParseStringHelper() { // We're about to handle an escape, copy all bytes from last to data. if (last < data) { parsed_storage_.append(last, data - last); - last = data; } // If we ran out of string after the \, cancel or report an error // depending on if we expect more data later. @@ -376,7 +375,6 @@ util::Status JsonStreamParser::ParseStringHelper() { } else { if (last < data) { parsed_storage_.append(last, data - last); - last = data; } parsed_ = StringPiece(parsed_storage_); } diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index 03a334b6..328b40d8 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -626,6 +626,7 @@ bool MessageDifferencer::CompareWithFieldsInternal( } if (reporter_ != NULL) { + assert(field1 != NULL); int count = field1->is_repeated() ? reflection1->FieldSize(message1, field1) : 1; @@ -706,6 +707,7 @@ bool MessageDifferencer::CompareWithFieldsInternal( } bool fieldDifferent = false; + assert(field1 != NULL); if (field1->is_repeated()) { fieldDifferent = !CompareRepeatedField(message1, message2, field1, parent_fields); @@ -875,6 +877,7 @@ bool MessageDifferencer::CompareRepeatedField( for (int i = 0; i < count1; ++i) { if (match_list1[i] != -1) continue; + assert(reporter_ != NULL); specific_field.index = i; parent_fields->push_back(specific_field); reporter_->ReportDeleted(message1, message2, *parent_fields); diff --git a/third_party/benchmark b/third_party/benchmark new file mode 160000 +Subproject 360e66c1c4777c99402cf8cd535aa510fee1657 |