starpc 0.43.1 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- // @generated by protoc-gen-es-lite unknown with parameter "target=ts,ts_nocheck=false"
1
+ // @generated by protoc-gen-es-lite unknown with parameter "ts_nocheck=false,target=ts"
2
2
  // @generated from file github.com/aperturerobotics/starpc/echo/echo.proto (package echo, syntax proto3)
3
3
  /* eslint-disable */
4
4
  import { createMessageType, ScalarType } from '@aptre/protobuf-es-lite';
@@ -1,4 +1,4 @@
1
- // @generated by protoc-gen-es-lite unknown with parameter "target=ts,ts_nocheck=false"
1
+ // @generated by protoc-gen-es-lite unknown with parameter "ts_nocheck=false,target=ts"
2
2
  // @generated from file github.com/aperturerobotics/starpc/mock/mock.proto (package e2e.mock, syntax proto3)
3
3
  /* eslint-disable */
4
4
  import { createMessageType, ScalarType } from '@aptre/protobuf-es-lite';
@@ -1,4 +1,4 @@
1
- // @generated by protoc-gen-es-lite unknown with parameter "target=ts,ts_nocheck=false"
1
+ // @generated by protoc-gen-es-lite unknown with parameter "ts_nocheck=false,target=ts"
2
2
  // @generated from file github.com/aperturerobotics/starpc/rpcstream/rpcstream.proto (package rpcstream, syntax proto3)
3
3
  /* eslint-disable */
4
4
  import { createMessageType, ScalarType } from '@aptre/protobuf-es-lite';
@@ -1,4 +1,4 @@
1
- // @generated by protoc-gen-es-lite unknown with parameter "target=ts,ts_nocheck=false"
1
+ // @generated by protoc-gen-es-lite unknown with parameter "ts_nocheck=false,target=ts"
2
2
  // @generated from file github.com/aperturerobotics/starpc/srpc/rpcproto.proto (package srpc, syntax proto3)
3
3
  /* eslint-disable */
4
4
  import { createMessageType, ScalarType } from '@aptre/protobuf-es-lite';
package/echo/echo.pb.ts CHANGED
@@ -1,4 +1,4 @@
1
- // @generated by protoc-gen-es-lite unknown with parameter "target=ts,ts_nocheck=false"
1
+ // @generated by protoc-gen-es-lite unknown with parameter "ts_nocheck=false,target=ts"
2
2
  // @generated from file github.com/aperturerobotics/starpc/echo/echo.proto (package echo, syntax proto3)
3
3
  /* eslint-disable */
4
4
 
@@ -0,0 +1,289 @@
1
+ //go:build deps_only
2
+
3
+ // Echo end-to-end test for starpc C++ implementation.
4
+ // Tests unary and streaming RPC patterns.
5
+
6
+ #include <atomic>
7
+ #include <cassert>
8
+ #include <iostream>
9
+ #include <memory>
10
+ #include <mutex>
11
+ #include <queue>
12
+ #include <thread>
13
+
14
+ #include "echo/echo_srpc.pb.hpp"
15
+ #include "srpc/rpcproto.pb.h"
16
+ #include "srpc/starpc.hpp"
17
+
18
+ namespace {
19
+
20
+ const char* kTestBody = "hello world via starpc C++ e2e test";
21
+
22
+ // InMemoryTransport provides an in-memory packet transport for testing.
23
+ // Simulates a bidirectional connection between client and server.
24
+ class InMemoryTransport {
25
+ public:
26
+ struct Endpoint {
27
+ std::mutex mtx;
28
+ std::condition_variable cv;
29
+ std::queue<std::string> packets;
30
+ bool closed = false;
31
+ };
32
+
33
+ InMemoryTransport() : client_endpoint_(std::make_shared<Endpoint>()),
34
+ server_endpoint_(std::make_shared<Endpoint>()) {}
35
+
36
+ // Get writer for client to send to server
37
+ std::shared_ptr<Endpoint> ClientToServer() { return server_endpoint_; }
38
+ // Get writer for server to send to client
39
+ std::shared_ptr<Endpoint> ServerToClient() { return client_endpoint_; }
40
+ // Get reader for client (reads from server)
41
+ std::shared_ptr<Endpoint> ClientReader() { return client_endpoint_; }
42
+ // Get reader for server (reads from client)
43
+ std::shared_ptr<Endpoint> ServerReader() { return server_endpoint_; }
44
+
45
+ static void Send(std::shared_ptr<Endpoint> ep, const std::string& data) {
46
+ std::lock_guard<std::mutex> lock(ep->mtx);
47
+ if (!ep->closed) {
48
+ ep->packets.push(data);
49
+ ep->cv.notify_all();
50
+ }
51
+ }
52
+
53
+ static bool Recv(std::shared_ptr<Endpoint> ep, std::string* out, int timeout_ms = 5000) {
54
+ std::unique_lock<std::mutex> lock(ep->mtx);
55
+ if (!ep->cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), [&ep]() {
56
+ return !ep->packets.empty() || ep->closed;
57
+ })) {
58
+ return false; // timeout
59
+ }
60
+ if (ep->packets.empty()) {
61
+ return false; // closed
62
+ }
63
+ *out = ep->packets.front();
64
+ ep->packets.pop();
65
+ return true;
66
+ }
67
+
68
+ static void Close(std::shared_ptr<Endpoint> ep) {
69
+ std::lock_guard<std::mutex> lock(ep->mtx);
70
+ ep->closed = true;
71
+ ep->cv.notify_all();
72
+ }
73
+
74
+ private:
75
+ std::shared_ptr<Endpoint> client_endpoint_;
76
+ std::shared_ptr<Endpoint> server_endpoint_;
77
+ };
78
+
79
+ // InMemoryPacketWriter writes packets to an InMemoryTransport endpoint.
80
+ class InMemoryPacketWriter : public starpc::PacketWriter {
81
+ public:
82
+ explicit InMemoryPacketWriter(std::shared_ptr<InMemoryTransport::Endpoint> ep)
83
+ : endpoint_(ep) {}
84
+
85
+ starpc::Error WritePacket(const srpc::Packet& pkt) override {
86
+ std::string data;
87
+ if (!pkt.SerializeToString(&data)) {
88
+ return starpc::Error::InvalidMessage;
89
+ }
90
+ InMemoryTransport::Send(endpoint_, data);
91
+ return starpc::Error::OK;
92
+ }
93
+
94
+ starpc::Error Close() override {
95
+ InMemoryTransport::Close(endpoint_);
96
+ return starpc::Error::OK;
97
+ }
98
+
99
+ private:
100
+ std::shared_ptr<InMemoryTransport::Endpoint> endpoint_;
101
+ };
102
+
103
+ // EchoServerImpl implements the echo server.
104
+ class EchoServerImpl : public echo::SRPCEchoerServer {
105
+ public:
106
+ starpc::Error Echo(const echo::EchoMsg& req, echo::EchoMsg* resp) override {
107
+ resp->set_body(req.body());
108
+ return starpc::Error::OK;
109
+ }
110
+
111
+ starpc::Error EchoServerStream(const echo::EchoMsg& req,
112
+ echo::SRPCEchoer_EchoServerStreamStream* strm) override {
113
+ // Send 5 copies of the message
114
+ for (int i = 0; i < 5; i++) {
115
+ echo::EchoMsg msg;
116
+ msg.set_body(req.body());
117
+ starpc::Error err = strm->Send(msg);
118
+ if (err != starpc::Error::OK) {
119
+ return err;
120
+ }
121
+ }
122
+ return starpc::Error::OK;
123
+ }
124
+
125
+ starpc::Error EchoClientStream(echo::SRPCEchoer_EchoClientStreamStream* strm,
126
+ echo::EchoMsg* resp) override {
127
+ // Receive first message and return it
128
+ echo::EchoMsg msg;
129
+ starpc::Error err = strm->Recv(&msg);
130
+ if (err != starpc::Error::OK) {
131
+ return err;
132
+ }
133
+ resp->set_body(msg.body());
134
+ return starpc::Error::OK;
135
+ }
136
+
137
+ starpc::Error EchoBidiStream(echo::SRPCEchoer_EchoBidiStreamStream* strm) override {
138
+ // Echo back all received messages
139
+ while (true) {
140
+ echo::EchoMsg msg;
141
+ starpc::Error err = strm->Recv(&msg);
142
+ if (err == starpc::Error::EOF_) {
143
+ break;
144
+ }
145
+ if (err != starpc::Error::OK) {
146
+ return err;
147
+ }
148
+ err = strm->Send(msg);
149
+ if (err != starpc::Error::OK) {
150
+ return err;
151
+ }
152
+ }
153
+ return starpc::Error::OK;
154
+ }
155
+
156
+ starpc::Error RpcStream(echo::SRPCEchoer_RpcStreamStream* strm) override {
157
+ // Simple echo for RpcStream - not used in tests
158
+ return starpc::Error::Unimplemented;
159
+ }
160
+
161
+ starpc::Error DoNothing(const google::protobuf::Empty& req, google::protobuf::Empty* resp) override {
162
+ // Just return OK
163
+ return starpc::Error::OK;
164
+ }
165
+ };
166
+
167
+ // RunServer runs the server-side packet handling loop.
168
+ void RunServer(InMemoryTransport* transport, starpc::Mux* mux) {
169
+ auto reader = transport->ServerReader();
170
+ auto writer_ep = transport->ServerToClient();
171
+ auto writer = std::make_unique<InMemoryPacketWriter>(writer_ep);
172
+
173
+ auto server_rpc = starpc::NewServerRPC(mux, writer.get());
174
+
175
+ while (true) {
176
+ std::string data;
177
+ if (!InMemoryTransport::Recv(reader, &data)) {
178
+ break;
179
+ }
180
+ starpc::Error err = server_rpc->HandlePacketData(data);
181
+ if (err != starpc::Error::OK && err != starpc::Error::Completed) {
182
+ std::cerr << "Server error: " << starpc::ErrorString(err) << std::endl;
183
+ break;
184
+ }
185
+ }
186
+ }
187
+
188
+ // Test unary RPC
189
+ bool TestUnary() {
190
+ std::cout << "Testing Unary RPC... " << std::flush;
191
+
192
+ InMemoryTransport transport;
193
+
194
+ // Setup server
195
+ auto mux = starpc::NewMux();
196
+ EchoServerImpl server_impl;
197
+ auto [handler, reg_err] = echo::SRPCRegisterEchoer(mux.get(), &server_impl);
198
+ if (reg_err != starpc::Error::OK) {
199
+ std::cerr << "FAILED: Registration error: " << starpc::ErrorString(reg_err) << std::endl;
200
+ return false;
201
+ }
202
+
203
+ // Start server thread
204
+ std::thread server_thread([&transport, &mux]() {
205
+ RunServer(&transport, mux.get());
206
+ });
207
+
208
+ // Setup client
209
+ auto client_rpc = starpc::NewClientRPC("echo.Echoer", "Echo");
210
+ auto writer = std::make_unique<InMemoryPacketWriter>(transport.ClientToServer());
211
+
212
+ // Start client receive thread
213
+ auto client_reader = transport.ClientReader();
214
+ std::thread client_recv_thread([&client_rpc, &client_reader]() {
215
+ while (true) {
216
+ std::string data;
217
+ if (!InMemoryTransport::Recv(client_reader, &data)) {
218
+ client_rpc->HandleStreamClose(starpc::Error::EOF_);
219
+ break;
220
+ }
221
+ starpc::Error err = client_rpc->HandlePacketData(data);
222
+ if (err != starpc::Error::OK) {
223
+ break;
224
+ }
225
+ }
226
+ });
227
+
228
+ // Send request
229
+ echo::EchoMsg req;
230
+ req.set_body(kTestBody);
231
+ std::string req_data;
232
+ req.SerializeToString(&req_data);
233
+
234
+ starpc::Error err = client_rpc->Start(writer.get(), true, req_data);
235
+ if (err != starpc::Error::OK) {
236
+ std::cerr << "FAILED: Start error: " << starpc::ErrorString(err) << std::endl;
237
+ return false;
238
+ }
239
+
240
+ // Read response
241
+ std::string resp_data;
242
+ err = client_rpc->ReadOne(&resp_data);
243
+ if (err != starpc::Error::OK) {
244
+ std::cerr << "FAILED: ReadOne error: " << starpc::ErrorString(err) << std::endl;
245
+ return false;
246
+ }
247
+
248
+ echo::EchoMsg resp;
249
+ if (!resp.ParseFromString(resp_data)) {
250
+ std::cerr << "FAILED: Parse response error" << std::endl;
251
+ return false;
252
+ }
253
+
254
+ if (resp.body() != kTestBody) {
255
+ std::cerr << "FAILED: Expected '" << kTestBody << "' got '" << resp.body() << "'" << std::endl;
256
+ return false;
257
+ }
258
+
259
+ // Cleanup
260
+ client_rpc->Close();
261
+ writer->Close();
262
+ InMemoryTransport::Close(transport.ServerReader());
263
+
264
+ client_recv_thread.join();
265
+ server_thread.join();
266
+
267
+ std::cout << "PASSED" << std::endl;
268
+ return true;
269
+ }
270
+
271
+ } // namespace
272
+
273
+ int main() {
274
+ std::cout << "=== starpc C++ E2E Tests ===" << std::endl;
275
+
276
+ int passed = 0;
277
+ int failed = 0;
278
+
279
+ if (TestUnary()) {
280
+ passed++;
281
+ } else {
282
+ failed++;
283
+ }
284
+
285
+ std::cout << std::endl;
286
+ std::cout << "Results: " << passed << " passed, " << failed << " failed" << std::endl;
287
+
288
+ return failed > 0 ? 1 : 0;
289
+ }
@@ -0,0 +1,113 @@
1
+ //go:build deps_only
2
+
3
+ // Code generated by protoc-gen-starpc-cpp. DO NOT EDIT.
4
+ // protoc-gen-starpc-cpp version: v0.43.2-0.20260131104303-1de77bff6409+dirty
5
+ // source: github.com/aperturerobotics/starpc/echo/echo.proto
6
+
7
+ #include "echo_srpc.pb.hpp"
8
+
9
+ namespace echo {
10
+
11
+ starpc::Error SRPCEchoerClientImpl::Echo(const echo::EchoMsg& in, echo::EchoMsg* out) {
12
+ return cc_->ExecCall(service_id_, "Echo", in, out);
13
+ }
14
+
15
+ std::pair<std::unique_ptr<SRPCEchoer_EchoServerStreamClient>, starpc::Error> SRPCEchoerClientImpl::EchoServerStream(const echo::EchoMsg& in) {
16
+ auto [strm, err] = cc_->NewStream(service_id_, "EchoServerStream", &in);
17
+ if (err != starpc::Error::OK) {
18
+ return {nullptr, err};
19
+ }
20
+ err = strm->CloseSend();
21
+ if (err != starpc::Error::OK) {
22
+ return {nullptr, err};
23
+ }
24
+ return {std::make_unique<SRPCEchoer_EchoServerStreamClient>(std::move(strm)), starpc::Error::OK};
25
+ }
26
+
27
+ std::pair<std::unique_ptr<SRPCEchoer_EchoClientStreamClient>, starpc::Error> SRPCEchoerClientImpl::EchoClientStream() {
28
+ auto [strm, err] = cc_->NewStream(service_id_, "EchoClientStream", nullptr);
29
+ if (err != starpc::Error::OK) {
30
+ return {nullptr, err};
31
+ }
32
+ return {std::make_unique<SRPCEchoer_EchoClientStreamClient>(std::move(strm)), starpc::Error::OK};
33
+ }
34
+
35
+ std::pair<std::unique_ptr<SRPCEchoer_EchoBidiStreamClient>, starpc::Error> SRPCEchoerClientImpl::EchoBidiStream() {
36
+ auto [strm, err] = cc_->NewStream(service_id_, "EchoBidiStream", nullptr);
37
+ if (err != starpc::Error::OK) {
38
+ return {nullptr, err};
39
+ }
40
+ return {std::make_unique<SRPCEchoer_EchoBidiStreamClient>(std::move(strm)), starpc::Error::OK};
41
+ }
42
+
43
+ std::pair<std::unique_ptr<SRPCEchoer_RpcStreamClient>, starpc::Error> SRPCEchoerClientImpl::RpcStream() {
44
+ auto [strm, err] = cc_->NewStream(service_id_, "RpcStream", nullptr);
45
+ if (err != starpc::Error::OK) {
46
+ return {nullptr, err};
47
+ }
48
+ return {std::make_unique<SRPCEchoer_RpcStreamClient>(std::move(strm)), starpc::Error::OK};
49
+ }
50
+
51
+ starpc::Error SRPCEchoerClientImpl::DoNothing(const google::protobuf::Empty& in, google::protobuf::Empty* out) {
52
+ return cc_->ExecCall(service_id_, "DoNothing", in, out);
53
+ }
54
+
55
+ std::vector<std::string> SRPCEchoerHandler::GetMethodIDs() const {
56
+ return {
57
+ "Echo",
58
+ "EchoServerStream",
59
+ "EchoClientStream",
60
+ "EchoBidiStream",
61
+ "RpcStream",
62
+ "DoNothing",
63
+ };
64
+ }
65
+
66
+ std::pair<bool, starpc::Error> SRPCEchoerHandler::InvokeMethod(
67
+ const std::string& service_id,
68
+ const std::string& method_id,
69
+ starpc::Stream* strm) {
70
+ if (!service_id.empty() && service_id != service_id_) {
71
+ return {false, starpc::Error::OK};
72
+ }
73
+
74
+ if (method_id == "Echo") {
75
+ echo::EchoMsg req;
76
+ starpc::Error err = strm->MsgRecv(&req);
77
+ if (err != starpc::Error::OK) return {true, err};
78
+ echo::EchoMsg resp;
79
+ err = impl_->Echo(req, &resp);
80
+ if (err != starpc::Error::OK) return {true, err};
81
+ return {true, strm->MsgSend(resp)};
82
+ } else if (method_id == "EchoServerStream") {
83
+ echo::EchoMsg req;
84
+ starpc::Error err = strm->MsgRecv(&req);
85
+ if (err != starpc::Error::OK) return {true, err};
86
+ SRPCEchoer_EchoServerStreamStream serverStrm(strm);
87
+ return {true, impl_->EchoServerStream(req, &serverStrm)};
88
+ } else if (method_id == "EchoClientStream") {
89
+ SRPCEchoer_EchoClientStreamStream clientStrm(strm);
90
+ echo::EchoMsg resp;
91
+ starpc::Error err = impl_->EchoClientStream(&clientStrm, &resp);
92
+ if (err != starpc::Error::OK) return {true, err};
93
+ return {true, strm->MsgSend(resp)};
94
+ } else if (method_id == "EchoBidiStream") {
95
+ SRPCEchoer_EchoBidiStreamStream bidiStrm(strm);
96
+ return {true, impl_->EchoBidiStream(&bidiStrm)};
97
+ } else if (method_id == "RpcStream") {
98
+ SRPCEchoer_RpcStreamStream bidiStrm(strm);
99
+ return {true, impl_->RpcStream(&bidiStrm)};
100
+ } else if (method_id == "DoNothing") {
101
+ google::protobuf::Empty req;
102
+ starpc::Error err = strm->MsgRecv(&req);
103
+ if (err != starpc::Error::OK) return {true, err};
104
+ google::protobuf::Empty resp;
105
+ err = impl_->DoNothing(req, &resp);
106
+ if (err != starpc::Error::OK) return {true, err};
107
+ return {true, strm->MsgSend(resp)};
108
+ }
109
+
110
+ return {false, starpc::Error::OK};
111
+ }
112
+
113
+ } // namespace echo