The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#) https://grpc.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

191 lines
6.1 KiB

#!/usr/bin/python2.7
from copy import deepcopy
def create(state, name):
me = getattr(state, name)
if not me.created:
new = me.copy()
new.created = True
cg = state.codegen.copy()
cg.lines.extend([
'config.init_%s(f, %s_args)' % (name, name)])
s = State(state.client, state.server, cg)
setattr(s, name, new)
yield s
def start_client(state):
if state.client.created and not state.client.started:
cg = state.codegen.copy()
cg.lines.extend([
'client_call = grpc_channel_create_call(f.client, f.client_cq, "/foo", "test.google.com", deadline);'
])
client = state.client.copy()
client.started = True
yield State(client, state.server, cg)
def request_server(state):
if state.server.created and not state.server.requested:
cg = state.codegen.copy()
tag = cg.make_tag('request_server')
cg.lines.extend([
'GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &server_call, &call_details, &request_metadata_recv, f.server_cq, tag(%d)))' % tag])
server = state.server.copy()
server.requested = True
yield State(state.client, server, cg)
def start_op(state, l, r):
local = getattr(state, l)
remote = getattr(state, r)
if not local.started:
return
for send_initial_metadata in [True, False]:
for send_message in [True, False]:
for send_close in [True, False]:
for receive_initial_metadata in [True, False]:
for receive_message in [True, False]:
for receive_close in [True, False]:
if ((not send_initial_metadata) and (not send_message) and (not send_close) and
(not receive_initial_metadata) and (not receive_message) and (not receive_close)):
continue
if local.sending_initial_metadata and send_initial_metadata: continue
if local.sending_message and send_message: continue
if local.sending_close and send_close: continue
if l == 'server' and receive_initial_metadata: continue
if local.receiving_initial_metadata and receive_initial_metadata: continue
if local.receiving_message and receive_message: continue
if local.receiving_close and receive_close: continue
local2 = local.copy()
cg = state.codegen.copy()
cg.lines.extend(['op = ops']);
tag = cg.make_tag('start_op_%s' % l)
if send_initial_metadata:
cg.lines.extend([
'op->type = GRPC_OP_SEND_INITIAL_METADATA;',
'op->data.send_initial_metadata.count = 0;',
'op++;'])
local2.sending_initial_metadata = tag
if send_message:
cg.lines.extend([
'op->type = GRPC_OP_SEND_MESSAGE;',
'op->data.send_message = %s_payload;' % l,
'op++;'])
local2.sending_message = tag
if send_close:
if l == 'client':
cg.lines.extend([
'op->type = GRPC_OP_SEND_CLOSE_FROM_CLIENT;',
'op++'])
else:
cg.lines.extend([
'op->type = GRPC_OP_SEND_STATUS_FROM_SERVER;',
'op++'])
local2.sending_close = tag
if receive_initial_metadata:
cg.lines.extend([
'op->type = GRPC_OP_RECV_INITIAL_METADATA;',
'op++'])
local2.receiving_initial_metadata = tag
if receive_message:
cg.lines.extend([
'op->type = GRPC_OP_RECV_MESSAGE;',
'op++'])
local2.receiving_message = tag
if receive_close:
if l == 'client':
cg.lines.extend([
'op->type = GRPC_OP_RECV_STATUS_ON_CLIENT;',
'op++'])
else:
cg.lines.extend([
'op->type = GRPC_OP_RECV_CLOSE_ON_SERVER;',
'op++'])
local2.receiving_close = tag
cg.lines.extend([
'GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(%s_call, ops, op - ops, tag(%d)));' % (l, tag)])
s = State(state.client, state.server, cg)
setattr(s, l, local2)
yield s
def wrap(f, *a):
def g(state):
for x in f(state, *a):
yield x
return g
MUTATORS = [
wrap(create, 'client'),
wrap(create, 'server'),
wrap(start_op, 'client', 'server'),
wrap(start_op, 'server', 'client'),
start_client,
request_server,
]
class Codegen(object):
lines = []
next_tag = 1
last_tag_creator = 'nobody'
def generate(self):
print '{'
print '\n'.join(self.lines)
print '}'
def copy(self):
cg = deepcopy(self)
cg.lines = self.lines[:]
return cg
def make_tag(self, name):
self.last_tag_creator = name
tag = self.next_tag
self.next_tag += 1
return tag
class Endpoint(object):
created = False
started = False
requested = False
sent_initial_metadata = False
sent_messages = 0
sent_close = False
sending_initial_metadata = False
sending_message = False
sending_close = False
received_initial_metadata = False
received_messages = 0
received_close = False
receiving_initial_metadata = False
receiving_message = False
receiving_close = False
def copy(self):
return deepcopy(self)
class State(object):
def __init__(self, client, server, codegen):
self.client = client
self.server = server
self.codegen = codegen
def as_dict(self):
return {'client': self.client.as_dict(), 'server': self.server.as_dict()}
def mutations(self):
for mutator in MUTATORS:
for new_state in mutator(self):
yield new_state
count = 0
def generate(state, depth):
global count
n = 0
#print ' '*depth, state.as_dict()
for state2 in state.mutations():
n += 1
generate(state2, depth+1)
if n == 0:
count += 1
#state.codegen.generate()
generate(State(Endpoint(), Endpoint(), Codegen()), 0)
print count