From db110e4a8095932d276dcfd23859645deb385633 Mon Sep 17 00:00:00 2001 From: Ryan Sundberg Date: Fri, 18 Mar 2022 13:00:32 -0700 Subject: [PATCH 1/2] Makefile: Fix `protos` target and regenerate code The `protos` target should generate code under test/test/ instead of just test/ Signed-off-by: Ryan Sundberg --- Makefile | 3 +- test/test/com/example/addressbook.cljc | 63 +++--- test/test/com/example/empty.cljc | 75 ++++--- test/test/protojure/test/grpc.cljc | 117 +++++----- .../test/grpc/TestService/client.cljc | 206 +++++++++--------- .../test/grpc/TestService/server.cljc | 2 + 6 files changed, 240 insertions(+), 226 deletions(-) diff --git a/Makefile b/Makefile index 3229fbb..bafb94b 100644 --- a/Makefile +++ b/Makefile @@ -39,4 +39,5 @@ clean: .PHONY: protos protos: - protoc --clojure_out=grpc-client,grpc-server:test --proto_path=test/resources $(shell find test/resources -name "*.proto" | sed 's|test/resources/||g') + mkdir -p test/test/resources + protoc --clojure_out=grpc-client,grpc-server:test/test --proto_path=test/test/resources $(shell find test/test/resources -name "*.proto" | sed 's|test/test/resources/||g') diff --git a/test/test/com/example/addressbook.cljc b/test/test/com/example/addressbook.cljc index 2f242a7..0a31c69 100644 --- a/test/test/com/example/addressbook.cljc +++ b/test/test/com/example/addressbook.cljc @@ -39,9 +39,10 @@ ;----------------------------------------------------------------------------- (def Person-PhoneType-default :mobile) -(def Person-PhoneType-val2label {0 :mobile - 1 :home - 2 :work}) +(def Person-PhoneType-val2label { + 0 :mobile + 1 :home + 2 :work}) (def Person-PhoneType-label2val (set/map-invert Person-PhoneType-val2label)) @@ -58,6 +59,8 @@ ([tag options value os] (serdes.core/write-Enum tag options (get-Person-PhoneType value) os))) + + ;;---------------------------------------------------------------------------------- ;;---------------------------------------------------------------------------------- ;; Message Implementations @@ -82,23 +85,23 @@ (s/def :com.example.addressbook.Person/id int?) (s/def :com.example.addressbook.Person/email string?) -(s/def ::Person-spec (s/keys :opt-un [:com.example.addressbook.Person/name :com.example.addressbook.Person/id :com.example.addressbook.Person/email])) -(def Person-defaults {:name "" :id 0 :email "" :phones []}) +(s/def ::Person-spec (s/keys :opt-un [:com.example.addressbook.Person/name :com.example.addressbook.Person/id :com.example.addressbook.Person/email ])) +(def Person-defaults {:name "" :id 0 :email "" :phones [] }) (defn cis->Person "CodedInputStream to Person" [is] (->> (tag-map Person-defaults - (fn [tag index] - (case index - 1 [:name (serdes.core/cis->String is)] - 2 [:id (serdes.core/cis->Int32 is)] - 3 [:email (serdes.core/cis->String is)] - 4 [:phones (serdes.complex/cis->repeated ecis->Person-PhoneNumber is)] + (fn [tag index] + (case index + 1 [:name (serdes.core/cis->String is)] + 2 [:id (serdes.core/cis->Int32 is)] + 3 [:email (serdes.core/cis->String is)] + 4 [:phones (serdes.complex/cis->repeated ecis->Person-PhoneNumber is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->Person-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->Person-record))) (defn ecis->Person "Embedded CodedInputStream to Person" @@ -136,21 +139,21 @@ (s/def :com.example.addressbook.Person-PhoneNumber/number string?) (s/def :com.example.addressbook.Person-PhoneNumber/type (s/or :keyword keyword? :int int?)) -(s/def ::Person-PhoneNumber-spec (s/keys :opt-un [:com.example.addressbook.Person-PhoneNumber/number :com.example.addressbook.Person-PhoneNumber/type])) -(def Person-PhoneNumber-defaults {:number "" :type Person-PhoneType-default}) +(s/def ::Person-PhoneNumber-spec (s/keys :opt-un [:com.example.addressbook.Person-PhoneNumber/number :com.example.addressbook.Person-PhoneNumber/type ])) +(def Person-PhoneNumber-defaults {:number "" :type Person-PhoneType-default }) (defn cis->Person-PhoneNumber "CodedInputStream to Person-PhoneNumber" [is] (->> (tag-map Person-PhoneNumber-defaults - (fn [tag index] - (case index - 1 [:number (serdes.core/cis->String is)] - 2 [:type (cis->Person-PhoneType is)] + (fn [tag index] + (case index + 1 [:number (serdes.core/cis->String is)] + 2 [:type (cis->Person-PhoneType is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->Person-PhoneNumber-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->Person-PhoneNumber-record))) (defn ecis->Person-PhoneNumber "Embedded CodedInputStream to Person-PhoneNumber" @@ -185,19 +188,19 @@ "com.example.addressbook.AddressBook")) (s/def ::AddressBook-spec (s/keys :opt-un [])) -(def AddressBook-defaults {:people []}) +(def AddressBook-defaults {:people [] }) (defn cis->AddressBook "CodedInputStream to AddressBook" [is] (->> (tag-map AddressBook-defaults - (fn [tag index] - (case index - 1 [:people (serdes.complex/cis->repeated ecis->Person is)] + (fn [tag index] + (case index + 1 [:people (serdes.complex/cis->repeated ecis->Person is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->AddressBook-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->AddressBook-record))) (defn ecis->AddressBook "Embedded CodedInputStream to AddressBook" diff --git a/test/test/com/example/empty.cljc b/test/test/com/example/empty.cljc index 2112592..ded832a 100644 --- a/test/test/com/example/empty.cljc +++ b/test/test/com/example/empty.cljc @@ -39,18 +39,20 @@ (defn convert-Selection-opt [origkeyval] (cond - (get-in origkeyval [:opt :e]) (update-in origkeyval [:opt :e] new-Empty) - (get-in origkeyval [:opt :ne]) (update-in origkeyval [:opt :ne] new-NonEmpty) - :default origkeyval)) + (get-in origkeyval [:opt :e]) (update-in origkeyval [:opt :e] new-Empty) + (get-in origkeyval [:opt :ne]) (update-in origkeyval [:opt :ne] new-NonEmpty) + :default origkeyval)) (defn write-Selection-opt [opt os] (let [field (first opt) k (when-not (nil? field) (key field)) v (when-not (nil? field) (val field))] - (case k - :e (serdes.core/write-embedded 1 v os) - :ne (serdes.core/write-embedded 2 v os) - nil))) + (case k + :e (serdes.core/write-embedded 1 v os) + :ne (serdes.core/write-embedded 2 v os) + nil))) + + ;;---------------------------------------------------------------------------------- ;;---------------------------------------------------------------------------------- @@ -63,7 +65,8 @@ ;----------------------------------------------------------------------------- (defrecord Empty-record [] pb/Writer - (serialize [this os]) + (serialize [this os] +) pb/TypeReflection (gettype [this] "com.example.empty.Empty")) @@ -75,11 +78,11 @@ "CodedInputStream to Empty" [is] (->> (tag-map Empty-defaults - (fn [tag index] - (case index - [index (serdes.core/cis->undefined tag is)])) - is) - (map->Empty-record))) + (fn [tag index] + (case index + [index (serdes.core/cis->undefined tag is)])) + is) + (map->Empty-record))) (defn ecis->Empty "Embedded CodedInputStream to Empty" @@ -114,20 +117,20 @@ "com.example.empty.NonEmpty")) (s/def :com.example.empty.NonEmpty/i int?) -(s/def ::NonEmpty-spec (s/keys :opt-un [:com.example.empty.NonEmpty/i])) -(def NonEmpty-defaults {:i 0}) +(s/def ::NonEmpty-spec (s/keys :opt-un [:com.example.empty.NonEmpty/i ])) +(def NonEmpty-defaults {:i 0 }) (defn cis->NonEmpty "CodedInputStream to NonEmpty" [is] (->> (tag-map NonEmpty-defaults - (fn [tag index] - (case index - 1 [:i (serdes.core/cis->Int32 is)] + (fn [tag index] + (case index + 1 [:i (serdes.core/cis->Int32 is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->NonEmpty-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->NonEmpty-record))) (defn ecis->NonEmpty "Embedded CodedInputStream to NonEmpty" @@ -168,14 +171,14 @@ "CodedInputStream to Selection" [is] (->> (tag-map Selection-defaults - (fn [tag index] - (case index - 1 [:opt {:e (ecis->Empty is)}] - 2 [:opt {:ne (ecis->NonEmpty is)}] + (fn [tag index] + (case index + 1 [:opt {:e (ecis->Empty is)}] + 2 [:opt {:ne (ecis->NonEmpty is)}] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->Selection-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->Selection-record))) (defn ecis->Selection "Embedded CodedInputStream to Selection" @@ -218,14 +221,14 @@ "CodedInputStream to Container" [is] (->> (tag-map Container-defaults - (fn [tag index] - (case index - 1 [:e (ecis->Empty is)] - 2 [:ne (ecis->NonEmpty is)] - - [index (serdes.core/cis->undefined tag is)])) - is) - (map->Container-record))) + (fn [tag index] + (case index + 1 [:e (ecis->Empty is)] + 2 [:ne (ecis->NonEmpty is)] + + [index (serdes.core/cis->undefined tag is)])) + is) + (map->Container-record))) (defn ecis->Container "Embedded CodedInputStream to Container" diff --git a/test/test/protojure/test/grpc.cljc b/test/test/protojure/test/grpc.cljc index ffb3b13..ded1a86 100644 --- a/test/test/protojure/test/grpc.cljc +++ b/test/test/protojure/test/grpc.cljc @@ -49,10 +49,11 @@ ;----------------------------------------------------------------------------- (def BigPayload-Mode-default :mode-invalid) -(def BigPayload-Mode-val2label {0 :mode-invalid - 1 :mode-upload - 2 :mode-download - 3 :mode-bidi}) +(def BigPayload-Mode-val2label { + 0 :mode-invalid + 1 :mode-upload + 2 :mode-download + 3 :mode-bidi}) (def BigPayload-Mode-label2val (set/map-invert BigPayload-Mode-val2label)) @@ -69,6 +70,8 @@ ([tag options value os] (serdes.core/write-Enum tag options (get-BigPayload-Mode value) os))) + + ;;---------------------------------------------------------------------------------- ;;---------------------------------------------------------------------------------- ;; Message Implementations @@ -87,20 +90,20 @@ "protojure.test.grpc.CloseDetectRequest")) (s/def :protojure.test.grpc.CloseDetectRequest/id string?) -(s/def ::CloseDetectRequest-spec (s/keys :opt-un [:protojure.test.grpc.CloseDetectRequest/id])) -(def CloseDetectRequest-defaults {:id ""}) +(s/def ::CloseDetectRequest-spec (s/keys :opt-un [:protojure.test.grpc.CloseDetectRequest/id ])) +(def CloseDetectRequest-defaults {:id "" }) (defn cis->CloseDetectRequest "CodedInputStream to CloseDetectRequest" [is] (->> (tag-map CloseDetectRequest-defaults - (fn [tag index] - (case index - 1 [:id (serdes.core/cis->String is)] + (fn [tag index] + (case index + 1 [:id (serdes.core/cis->String is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->CloseDetectRequest-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->CloseDetectRequest-record))) (defn ecis->CloseDetectRequest "Embedded CodedInputStream to CloseDetectRequest" @@ -137,21 +140,21 @@ (s/def :protojure.test.grpc.FlowControlRequest/count int?) (s/def :protojure.test.grpc.FlowControlRequest/payload-size int?) -(s/def ::FlowControlRequest-spec (s/keys :opt-un [:protojure.test.grpc.FlowControlRequest/count :protojure.test.grpc.FlowControlRequest/payload-size])) -(def FlowControlRequest-defaults {:count 0 :payload-size 0}) +(s/def ::FlowControlRequest-spec (s/keys :opt-un [:protojure.test.grpc.FlowControlRequest/count :protojure.test.grpc.FlowControlRequest/payload-size ])) +(def FlowControlRequest-defaults {:count 0 :payload-size 0 }) (defn cis->FlowControlRequest "CodedInputStream to FlowControlRequest" [is] (->> (tag-map FlowControlRequest-defaults - (fn [tag index] - (case index - 1 [:count (serdes.core/cis->Int32 is)] - 2 [:payload-size (serdes.core/cis->Int32 is)] + (fn [tag index] + (case index + 1 [:count (serdes.core/cis->Int32 is)] + 2 [:payload-size (serdes.core/cis->Int32 is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->FlowControlRequest-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->FlowControlRequest-record))) (defn ecis->FlowControlRequest "Embedded CodedInputStream to FlowControlRequest" @@ -188,21 +191,21 @@ (s/def :protojure.test.grpc.FlowControlPayload/id int?) (s/def :protojure.test.grpc.FlowControlPayload/data bytes?) -(s/def ::FlowControlPayload-spec (s/keys :opt-un [:protojure.test.grpc.FlowControlPayload/id :protojure.test.grpc.FlowControlPayload/data])) -(def FlowControlPayload-defaults {:id 0 :data (byte-array 0)}) +(s/def ::FlowControlPayload-spec (s/keys :opt-un [:protojure.test.grpc.FlowControlPayload/id :protojure.test.grpc.FlowControlPayload/data ])) +(def FlowControlPayload-defaults {:id 0 :data (byte-array 0) }) (defn cis->FlowControlPayload "CodedInputStream to FlowControlPayload" [is] (->> (tag-map FlowControlPayload-defaults - (fn [tag index] - (case index - 1 [:id (serdes.core/cis->Int32 is)] - 2 [:data (serdes.core/cis->Bytes is)] + (fn [tag index] + (case index + 1 [:id (serdes.core/cis->Int32 is)] + 2 [:data (serdes.core/cis->Bytes is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->FlowControlPayload-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->FlowControlPayload-record))) (defn ecis->FlowControlPayload "Embedded CodedInputStream to FlowControlPayload" @@ -237,20 +240,20 @@ "protojure.test.grpc.SimpleResponse")) (s/def :protojure.test.grpc.SimpleResponse/msg string?) -(s/def ::SimpleResponse-spec (s/keys :opt-un [:protojure.test.grpc.SimpleResponse/msg])) -(def SimpleResponse-defaults {:msg ""}) +(s/def ::SimpleResponse-spec (s/keys :opt-un [:protojure.test.grpc.SimpleResponse/msg ])) +(def SimpleResponse-defaults {:msg "" }) (defn cis->SimpleResponse "CodedInputStream to SimpleResponse" [is] (->> (tag-map SimpleResponse-defaults - (fn [tag index] - (case index - 1 [:msg (serdes.core/cis->String is)] + (fn [tag index] + (case index + 1 [:msg (serdes.core/cis->String is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->SimpleResponse-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->SimpleResponse-record))) (defn ecis->SimpleResponse "Embedded CodedInputStream to SimpleResponse" @@ -287,21 +290,21 @@ (s/def :protojure.test.grpc.ErrorRequest/status int?) (s/def :protojure.test.grpc.ErrorRequest/message string?) -(s/def ::ErrorRequest-spec (s/keys :opt-un [:protojure.test.grpc.ErrorRequest/status :protojure.test.grpc.ErrorRequest/message])) -(def ErrorRequest-defaults {:status 0 :message ""}) +(s/def ::ErrorRequest-spec (s/keys :opt-un [:protojure.test.grpc.ErrorRequest/status :protojure.test.grpc.ErrorRequest/message ])) +(def ErrorRequest-defaults {:status 0 :message "" }) (defn cis->ErrorRequest "CodedInputStream to ErrorRequest" [is] (->> (tag-map ErrorRequest-defaults - (fn [tag index] - (case index - 1 [:status (serdes.core/cis->Int32 is)] - 2 [:message (serdes.core/cis->String is)] + (fn [tag index] + (case index + 1 [:status (serdes.core/cis->Int32 is)] + 2 [:message (serdes.core/cis->String is)] - [index (serdes.core/cis->undefined tag is)])) - is) - (map->ErrorRequest-record))) + [index (serdes.core/cis->undefined tag is)])) + is) + (map->ErrorRequest-record))) (defn ecis->ErrorRequest "Embedded CodedInputStream to ErrorRequest" @@ -338,21 +341,21 @@ (s/def :protojure.test.grpc.BigPayload/mode (s/or :keyword keyword? :int int?)) (s/def :protojure.test.grpc.BigPayload/data bytes?) -(s/def ::BigPayload-spec (s/keys :opt-un [:protojure.test.grpc.BigPayload/mode :protojure.test.grpc.BigPayload/data])) -(def BigPayload-defaults {:mode BigPayload-Mode-default :data (byte-array 0)}) +(s/def ::BigPayload-spec (s/keys :opt-un [:protojure.test.grpc.BigPayload/mode :protojure.test.grpc.BigPayload/data ])) +(def BigPayload-defaults {:mode BigPayload-Mode-default :data (byte-array 0) }) (defn cis->BigPayload "CodedInputStream to BigPayload" [is] (->> (tag-map BigPayload-defaults - (fn [tag index] - (case index - 1 [:mode (cis->BigPayload-Mode is)] - 2 [:data (serdes.core/cis->Bytes is)] - - [index (serdes.core/cis->undefined tag is)])) - is) - (map->BigPayload-record))) + (fn [tag index] + (case index + 1 [:mode (cis->BigPayload-Mode is)] + 2 [:data (serdes.core/cis->Bytes is)] + + [index (serdes.core/cis->undefined tag is)])) + is) + (map->BigPayload-record))) (defn ecis->BigPayload "Embedded CodedInputStream to BigPayload" diff --git a/test/test/protojure/test/grpc/TestService/client.cljc b/test/test/protojure/test/grpc/TestService/client.cljc index 5c54ac9..865099d 100644 --- a/test/test/protojure/test/grpc/TestService/client.cljc +++ b/test/test/protojure/test/grpc/TestService/client.cljc @@ -15,153 +15,155 @@ ; GRPC Client Implementation ;----------------------------------------------------------------------------- +(def TestService-service-name "protojure.test.grpc.TestService") + (defn BandwidthTest ([client params] (BandwidthTest client {} params)) ([client metadata params] - (let [input (async/chan 1) - output (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "BandwidthTest" - :input {:f protojure.test.grpc/new-BigPayload :ch input} - :output {:f protojure.test.grpc/pb->BigPayload :ch output} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (invoke-unary client desc output))))))) + (let [input (async/chan 1) + output (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "BandwidthTest" + :input {:f protojure.test.grpc/new-BigPayload :ch input} + :output {:f protojure.test.grpc/pb->BigPayload :ch output} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (invoke-unary client desc output))))))) (defn ClientCloseDetect ([client params reply] (ClientCloseDetect client {} params reply)) ([client metadata params reply] - (let [input (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "ClientCloseDetect" - :input {:f protojure.test.grpc/new-CloseDetectRequest :ch input} - :output {:f com.google.protobuf/pb->Any :ch reply} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (grpc/invoke client desc))))))) + (let [input (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "ClientCloseDetect" + :input {:f protojure.test.grpc/new-CloseDetectRequest :ch input} + :output {:f com.google.protobuf/pb->Any :ch reply} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (grpc/invoke client desc))))))) (defn FlowControl ([client params reply] (FlowControl client {} params reply)) ([client metadata params reply] - (let [input (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "FlowControl" - :input {:f protojure.test.grpc/new-FlowControlRequest :ch input} - :output {:f protojure.test.grpc/pb->FlowControlPayload :ch reply} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (grpc/invoke client desc))))))) + (let [input (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "FlowControl" + :input {:f protojure.test.grpc/new-FlowControlRequest :ch input} + :output {:f protojure.test.grpc/pb->FlowControlPayload :ch reply} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (grpc/invoke client desc))))))) (defn ReturnError ([client params] (ReturnError client {} params)) ([client metadata params] - (let [input (async/chan 1) - output (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "ReturnError" - :input {:f protojure.test.grpc/new-ErrorRequest :ch input} - :output {:f com.google.protobuf/pb->Empty :ch output} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (invoke-unary client desc output))))))) + (let [input (async/chan 1) + output (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "ReturnError" + :input {:f protojure.test.grpc/new-ErrorRequest :ch input} + :output {:f com.google.protobuf/pb->Empty :ch output} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (invoke-unary client desc output))))))) (defn AllEmpty ([client params] (AllEmpty client {} params)) ([client metadata params] - (let [input (async/chan 1) - output (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "AllEmpty" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f com.google.protobuf/pb->Empty :ch output} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (invoke-unary client desc output))))))) + (let [input (async/chan 1) + output (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "AllEmpty" + :input {:f com.google.protobuf/new-Empty :ch input} + :output {:f com.google.protobuf/pb->Empty :ch output} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (invoke-unary client desc output))))))) (defn ServerCloseDetect ([client params reply] (ServerCloseDetect client {} params reply)) ([client metadata params reply] - (let [input (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "ServerCloseDetect" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f com.google.protobuf/pb->Any :ch reply} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (grpc/invoke client desc))))))) + (let [input (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "ServerCloseDetect" + :input {:f com.google.protobuf/new-Empty :ch input} + :output {:f com.google.protobuf/pb->Any :ch reply} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (grpc/invoke client desc))))))) (defn Async ([client params] (Async client {} params)) ([client metadata params] - (let [input (async/chan 1) - output (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "Async" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f protojure.test.grpc/pb->SimpleResponse :ch output} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (invoke-unary client desc output))))))) + (let [input (async/chan 1) + output (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "Async" + :input {:f com.google.protobuf/new-Empty :ch input} + :output {:f protojure.test.grpc/pb->SimpleResponse :ch output} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (invoke-unary client desc output))))))) (defn DeniedStreamer ([client params reply] (DeniedStreamer client {} params reply)) ([client metadata params reply] - (let [input (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "DeniedStreamer" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f com.google.protobuf/pb->Empty :ch reply} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (grpc/invoke client desc))))))) + (let [input (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "DeniedStreamer" + :input {:f com.google.protobuf/new-Empty :ch input} + :output {:f com.google.protobuf/pb->Empty :ch reply} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (grpc/invoke client desc))))))) (defn AsyncEmpty ([client params reply] (AsyncEmpty client {} params reply)) ([client metadata params reply] - (let [input (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "AsyncEmpty" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f com.google.protobuf/pb->Empty :ch reply} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (grpc/invoke client desc))))))) + (let [input (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "AsyncEmpty" + :input {:f com.google.protobuf/new-Empty :ch input} + :output {:f com.google.protobuf/pb->Empty :ch reply} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (grpc/invoke client desc))))))) (defn Metadata ([client params] (Metadata client {} params)) ([client metadata params] - (let [input (async/chan 1) - output (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "Metadata" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f protojure.test.grpc/pb->SimpleResponse :ch output} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (invoke-unary client desc output))))))) + (let [input (async/chan 1) + output (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "Metadata" + :input {:f com.google.protobuf/new-Empty :ch input} + :output {:f protojure.test.grpc/pb->SimpleResponse :ch output} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (invoke-unary client desc output))))))) (defn ReturnErrorStreaming ([client params reply] (ReturnErrorStreaming client {} params reply)) ([client metadata params reply] - (let [input (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "ReturnErrorStreaming" - :input {:f protojure.test.grpc/new-ErrorRequest :ch input} - :output {:f com.google.protobuf/pb->Empty :ch reply} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (grpc/invoke client desc))))))) + (let [input (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "ReturnErrorStreaming" + :input {:f protojure.test.grpc/new-ErrorRequest :ch input} + :output {:f com.google.protobuf/pb->Empty :ch reply} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (grpc/invoke client desc))))))) (defn ShouldThrow ([client params] (ShouldThrow client {} params)) ([client metadata params] - (let [input (async/chan 1) - output (async/chan 1) - desc {:service "protojure.test.grpc.TestService" - :method "ShouldThrow" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f com.google.protobuf/pb->Empty :ch output} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (invoke-unary client desc output))))))) + (let [input (async/chan 1) + output (async/chan 1) + desc {:service "protojure.test.grpc.TestService" + :method "ShouldThrow" + :input {:f com.google.protobuf/new-Empty :ch input} + :output {:f com.google.protobuf/pb->Empty :ch output} + :metadata metadata}] + (-> (send-unary-params input params) + (p/then (fn [_] (invoke-unary client desc output))))))) diff --git a/test/test/protojure/test/grpc/TestService/server.cljc b/test/test/protojure/test/grpc/TestService/server.cljc index 2d544b3..cedb18d 100644 --- a/test/test/protojure/test/grpc/TestService/server.cljc +++ b/test/test/protojure/test/grpc/TestService/server.cljc @@ -24,6 +24,8 @@ (ReturnErrorStreaming [this param]) (ShouldThrow [this param])) +(def TestService-service-name "protojure.test.grpc.TestService") + (defn- BandwidthTest-dispatch [ctx request] (BandwidthTest ctx request)) From f4a74d94939855683dad67c6b62039d4eb0aa305 Mon Sep 17 00:00:00 2001 From: Ryan Sundberg Date: Fri, 18 Mar 2022 13:27:30 -0700 Subject: [PATCH 2/2] New test case: RPC handler when lazy response data throws an error This reproduces a bug where an exception raised in a lazy sequence attached to a protobuf response causes the request handler to crash and time out. Signed-off-by: Ryan Sundberg --- test/test/protojure/grpc_test.clj | 44 ++++++-- test/test/protojure/test/grpc.cljc | 102 ++++++++++++++++++ .../test/grpc/TestService/client.cljc | 4 +- .../test/grpc/TestService/server.cljc | 2 +- test/test/resources/grpctest.proto | 12 ++- 5 files changed, 149 insertions(+), 15 deletions(-) diff --git a/test/test/protojure/grpc_test.clj b/test/test/protojure/grpc_test.clj index f3fd9b0..d7a0d13 100644 --- a/test/test/protojure/grpc_test.clj +++ b/test/test/protojure/grpc_test.clj @@ -183,8 +183,20 @@ {:body {:msg (str "Hello, " auth)}})) (ShouldThrow - [_ request] - (throw (ex-info "This is supposed to fail" {}))) + [_ {{test-case :case} :grpc-params}] + {:body + (case test-case + 0 (throw (ex-info "This is supposed to fail" {})) + ; Non-lazy seq + 1 {:numbers + (mapv (fn [_] + (throw (ex-info "This is also supposed to fail (1)" {}))) + (range 3))} + ; Lazy seq + 2 {:numbers + (map (fn [n] + (throw (ex-info "This is also supposed to fail (2)" {}))) + (range 3))})}) (Async [_ request] @@ -262,6 +274,16 @@ [code & body] `(-check-throw ~code #(do ~@body))) +(defn is-grpc-error? [grpc-status response-promise] + "Asserts that response promise returns a specific gRPC error code, and + returns the exception." + (let [ex (is (thrown? Exception @response-promise)) + cause (.getCause ex) + code (grpc.status/get-code grpc-status)] + (is (some? cause)) + (is (= code (:status (ex-data cause)))) + cause)) + ;;----------------------------------------------------------------------------- ;; Scaletest Assemblies ;;----------------------------------------------------------------------------- @@ -680,18 +702,20 @@ (deftest test-grpc-exception (let [client @(grpc.http2/connect {:uri (str "http://localhost:" (:port @test-env))})] (testing "Check that exceptions thrown on the server propagate back to the client" - (is (thrown? java.util.concurrent.ExecutionException - @(test.client/ShouldThrow client {}))) - (try - @(test.client/ShouldThrow client {}) - (assert false) ;; we should never get here - (catch java.util.concurrent.ExecutionException e - (let [{:keys [status]} (ex-data (.getCause e))] - (is (= status 13)))))) + (is-grpc-error? :internal (test.client/ShouldThrow client {}))) (testing "Check that we can still connect even after exceptions have been received" (is (-> @(test.client/Async client {}) :msg (= "Hello, Async")))) (grpc/disconnect client))) +(deftest test-grpc-sequence-exception + (let [client @(grpc.http2/connect {:uri (str "http://localhost:" (:port @test-env))})] + (testing "Check that exceptions thrown in sequence mappers on the server propagate back to the client" + (testing "Non-lazy: throws in mapv" + (is-grpc-error? :internal (test.client/ShouldThrow client {:case 1}))) + (testing "Lazy: throws in map" + (is-grpc-error? :internal (test.client/ShouldThrow client {:case 2})))) + (grpc/disconnect client))) + (deftest test-grpc-async (testing "Check that async processing functions correctly" (let [client @(grpc.http2/connect {:uri (str "http://localhost:" (:port @test-env))})] diff --git a/test/test/protojure/test/grpc.cljc b/test/test/protojure/test/grpc.cljc index ded1a86..52281c8 100644 --- a/test/test/protojure/test/grpc.cljc +++ b/test/test/protojure/test/grpc.cljc @@ -37,6 +37,12 @@ (declare cis->BigPayload) (declare ecis->BigPayload) (declare new-BigPayload) +(declare cis->ShouldThrowRequest) +(declare ecis->ShouldThrowRequest) +(declare new-ShouldThrowRequest) +(declare cis->ShouldThrowResponse) +(declare ecis->ShouldThrowResponse) +(declare new-ShouldThrowResponse) ;;---------------------------------------------------------------------------------- ;;---------------------------------------------------------------------------------- @@ -378,3 +384,99 @@ (def ^:protojure.protobuf.any/record BigPayload-meta {:type "protojure.test.grpc.BigPayload" :decoder pb->BigPayload}) +;----------------------------------------------------------------------------- +; ShouldThrowRequest +;----------------------------------------------------------------------------- +(defrecord ShouldThrowRequest-record [case] + pb/Writer + (serialize [this os] + (serdes.core/write-Int32 1 {:optimize true} (:case this) os)) + pb/TypeReflection + (gettype [this] + "protojure.test.grpc.ShouldThrowRequest")) + +(s/def :protojure.test.grpc.ShouldThrowRequest/case int?) +(s/def ::ShouldThrowRequest-spec (s/keys :opt-un [:protojure.test.grpc.ShouldThrowRequest/case ])) +(def ShouldThrowRequest-defaults {:case 0 }) + +(defn cis->ShouldThrowRequest + "CodedInputStream to ShouldThrowRequest" + [is] + (->> (tag-map ShouldThrowRequest-defaults + (fn [tag index] + (case index + 1 [:case (serdes.core/cis->Int32 is)] + + [index (serdes.core/cis->undefined tag is)])) + is) + (map->ShouldThrowRequest-record))) + +(defn ecis->ShouldThrowRequest + "Embedded CodedInputStream to ShouldThrowRequest" + [is] + (serdes.core/cis->embedded cis->ShouldThrowRequest is)) + +(defn new-ShouldThrowRequest + "Creates a new instance from a map, similar to map->ShouldThrowRequest except that + it properly accounts for nested messages, when applicable. + " + [init] + {:pre [(if (s/valid? ::ShouldThrowRequest-spec init) true (throw (ex-info "Invalid input" (s/explain-data ::ShouldThrowRequest-spec init))))]} + (-> (merge ShouldThrowRequest-defaults init) + (map->ShouldThrowRequest-record))) + +(defn pb->ShouldThrowRequest + "Protobuf to ShouldThrowRequest" + [input] + (cis->ShouldThrowRequest (serdes.stream/new-cis input))) + +(def ^:protojure.protobuf.any/record ShouldThrowRequest-meta {:type "protojure.test.grpc.ShouldThrowRequest" :decoder pb->ShouldThrowRequest}) + +;----------------------------------------------------------------------------- +; ShouldThrowResponse +;----------------------------------------------------------------------------- +(defrecord ShouldThrowResponse-record [numbers] + pb/Writer + (serialize [this os] + (serdes.complex/write-repeated serdes.core/write-Int32 1 (:numbers this) os)) + pb/TypeReflection + (gettype [this] + "protojure.test.grpc.ShouldThrowResponse")) + +(s/def :protojure.test.grpc.ShouldThrowResponse/numbers (s/every int?)) +(s/def ::ShouldThrowResponse-spec (s/keys :opt-un [:protojure.test.grpc.ShouldThrowResponse/numbers ])) +(def ShouldThrowResponse-defaults {:numbers [] }) + +(defn cis->ShouldThrowResponse + "CodedInputStream to ShouldThrowResponse" + [is] + (->> (tag-map ShouldThrowResponse-defaults + (fn [tag index] + (case index + 1 [:numbers (serdes.complex/cis->packablerepeated tag serdes.core/cis->Int32 is)] + + [index (serdes.core/cis->undefined tag is)])) + is) + (map->ShouldThrowResponse-record))) + +(defn ecis->ShouldThrowResponse + "Embedded CodedInputStream to ShouldThrowResponse" + [is] + (serdes.core/cis->embedded cis->ShouldThrowResponse is)) + +(defn new-ShouldThrowResponse + "Creates a new instance from a map, similar to map->ShouldThrowResponse except that + it properly accounts for nested messages, when applicable. + " + [init] + {:pre [(if (s/valid? ::ShouldThrowResponse-spec init) true (throw (ex-info "Invalid input" (s/explain-data ::ShouldThrowResponse-spec init))))]} + (-> (merge ShouldThrowResponse-defaults init) + (map->ShouldThrowResponse-record))) + +(defn pb->ShouldThrowResponse + "Protobuf to ShouldThrowResponse" + [input] + (cis->ShouldThrowResponse (serdes.stream/new-cis input))) + +(def ^:protojure.protobuf.any/record ShouldThrowResponse-meta {:type "protojure.test.grpc.ShouldThrowResponse" :decoder pb->ShouldThrowResponse}) + diff --git a/test/test/protojure/test/grpc/TestService/client.cljc b/test/test/protojure/test/grpc/TestService/client.cljc index 865099d..59a0b6e 100644 --- a/test/test/protojure/test/grpc/TestService/client.cljc +++ b/test/test/protojure/test/grpc/TestService/client.cljc @@ -161,8 +161,8 @@ output (async/chan 1) desc {:service "protojure.test.grpc.TestService" :method "ShouldThrow" - :input {:f com.google.protobuf/new-Empty :ch input} - :output {:f com.google.protobuf/pb->Empty :ch output} + :input {:f protojure.test.grpc/new-ShouldThrowRequest :ch input} + :output {:f protojure.test.grpc/pb->ShouldThrowResponse :ch output} :metadata metadata}] (-> (send-unary-params input params) (p/then (fn [_] (invoke-unary client desc output))))))) diff --git a/test/test/protojure/test/grpc/TestService/server.cljc b/test/test/protojure/test/grpc/TestService/server.cljc index cedb18d..3403d6d 100644 --- a/test/test/protojure/test/grpc/TestService/server.cljc +++ b/test/test/protojure/test/grpc/TestService/server.cljc @@ -75,4 +75,4 @@ {:pkg "protojure.test.grpc" :service "TestService" :method "AsyncEmpty" :method-fn AsyncEmpty-dispatch :server-streaming true :client-streaming false :input com.google.protobuf/pb->Empty :output com.google.protobuf/new-Empty} {:pkg "protojure.test.grpc" :service "TestService" :method "Metadata" :method-fn Metadata-dispatch :server-streaming false :client-streaming false :input com.google.protobuf/pb->Empty :output new-SimpleResponse} {:pkg "protojure.test.grpc" :service "TestService" :method "ReturnErrorStreaming" :method-fn ReturnErrorStreaming-dispatch :server-streaming true :client-streaming false :input pb->ErrorRequest :output com.google.protobuf/new-Empty} - {:pkg "protojure.test.grpc" :service "TestService" :method "ShouldThrow" :method-fn ShouldThrow-dispatch :server-streaming false :client-streaming false :input com.google.protobuf/pb->Empty :output com.google.protobuf/new-Empty}]) + {:pkg "protojure.test.grpc" :service "TestService" :method "ShouldThrow" :method-fn ShouldThrow-dispatch :server-streaming false :client-streaming false :input pb->ShouldThrowRequest :output new-ShouldThrowResponse}]) diff --git a/test/test/resources/grpctest.proto b/test/test/resources/grpctest.proto index fc9639d..ebe1d1c 100644 --- a/test/test/resources/grpctest.proto +++ b/test/test/resources/grpctest.proto @@ -40,12 +40,20 @@ message BigPayload { bytes data = 2; } +message ShouldThrowRequest { + int32 case = 1; +} + +message ShouldThrowResponse { + repeated int32 numbers = 1; +} + service TestService { rpc ClientCloseDetect (CloseDetectRequest) returns (stream google.protobuf.Any); rpc ServerCloseDetect (google.protobuf.Empty) returns (stream google.protobuf.Any); rpc FlowControl (FlowControlRequest) returns (stream FlowControlPayload); rpc Metadata (google.protobuf.Empty) returns (SimpleResponse); - rpc ShouldThrow (google.protobuf.Empty) returns (google.protobuf.Empty); + rpc ShouldThrow (ShouldThrowRequest) returns (ShouldThrowResponse); rpc Async (google.protobuf.Empty) returns (SimpleResponse); rpc AllEmpty(google.protobuf.Empty) returns (google.protobuf.Empty); rpc AsyncEmpty(google.protobuf.Empty) returns (stream google.protobuf.Empty); @@ -53,4 +61,4 @@ service TestService { rpc ReturnError(ErrorRequest) returns (google.protobuf.Empty); rpc ReturnErrorStreaming(ErrorRequest) returns (stream google.protobuf.Empty); rpc BandwidthTest(BigPayload) returns (BigPayload); -} \ No newline at end of file +}