1*2cb6d6f1SJim Jagielski################################################################ 2*2cb6d6f1SJim Jagielski# 3*2cb6d6f1SJim Jagielski# Licensed to the Apache Software Foundation (ASF) under one 4*2cb6d6f1SJim Jagielski# or more contributor license agreements. See the NOTICE file 5*2cb6d6f1SJim Jagielski# distributed with this work for additional information 6*2cb6d6f1SJim Jagielski# regarding copyright ownership. The ASF licenses this file 7*2cb6d6f1SJim Jagielski# to you under the Apache License, Version 2.0 (the 8*2cb6d6f1SJim Jagielski# "License"); you may not use this file except in compliance 9*2cb6d6f1SJim Jagielski# with the License. You may obtain a copy of the License at 10*2cb6d6f1SJim Jagielski# 11*2cb6d6f1SJim Jagielski# http://www.apache.org/licenses/LICENSE-2.0 12*2cb6d6f1SJim Jagielski# 13*2cb6d6f1SJim Jagielski# Unless required by applicable law or agreed to in writing, 14*2cb6d6f1SJim Jagielski# software distributed under the License is distributed on an 15*2cb6d6f1SJim Jagielski# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*2cb6d6f1SJim Jagielski# KIND, either express or implied. See the License for the 17*2cb6d6f1SJim Jagielski# specific language governing permissions and limitations 18*2cb6d6f1SJim Jagielski# under the License. 19*2cb6d6f1SJim Jagielski# 20*2cb6d6f1SJim Jagielski################################################################ 21*2cb6d6f1SJim Jagielski 22*2cb6d6f1SJim Jagielski"""A stand-in for the real worker. usage: fake_worker.py <mode>. Modes other than 'good' misbehave in one specific way.""" 23*2cb6d6f1SJim Jagielskiimport json 24*2cb6d6f1SJim Jagielskiimport os 25*2cb6d6f1SJim Jagielskiimport signal 26*2cb6d6f1SJim Jagielskiimport subprocess 27*2cb6d6f1SJim Jagielskiimport sys 28*2cb6d6f1SJim Jagielskiimport time 29*2cb6d6f1SJim Jagielski 30*2cb6d6f1SJim Jagielskifrom aootest_worker.proto import Fail, serve 31*2cb6d6f1SJim Jagielski 32*2cb6d6f1SJim Jagielskimode = sys.argv[1] 33*2cb6d6f1SJim Jagielski 34*2cb6d6f1SJim Jagielski 35*2cb6d6f1SJim Jagielskidef hello(protocol=1): 36*2cb6d6f1SJim Jagielski print(json.dumps({"hello": {"protocol": protocol, "python": "3.14.0", "pid": os.getpid()}}), flush=True) 37*2cb6d6f1SJim Jagielski 38*2cb6d6f1SJim Jagielski 39*2cb6d6f1SJim Jagielskidef request(): 40*2cb6d6f1SJim Jagielski return json.loads(sys.stdin.readline()) 41*2cb6d6f1SJim Jagielski 42*2cb6d6f1SJim Jagielski 43*2cb6d6f1SJim Jagielskidef spawn_child(): 44*2cb6d6f1SJim Jagielski c = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(120)"]) 45*2cb6d6f1SJim Jagielski return {"pid": c.pid} 46*2cb6d6f1SJim Jagielski 47*2cb6d6f1SJim Jagielski 48*2cb6d6f1SJim Jagielskidef chatter(): 49*2cb6d6f1SJim Jagielski print("this goes to stderr, not into the protocol") 50*2cb6d6f1SJim Jagielski return {"printed": True} 51*2cb6d6f1SJim Jagielski 52*2cb6d6f1SJim Jagielski 53*2cb6d6f1SJim JagielskiOPS = { 54*2cb6d6f1SJim Jagielski "echo": lambda **kw: kw, 55*2cb6d6f1SJim Jagielski "add": lambda a, b: {"sum": a + b}, 56*2cb6d6f1SJim Jagielski "sleep": lambda seconds: time.sleep(seconds) or {}, 57*2cb6d6f1SJim Jagielski "fail": lambda kind, message="": (_ for _ in ()).throw(Fail(kind, message)), 58*2cb6d6f1SJim Jagielski "boom": lambda: 1 / 0, 59*2cb6d6f1SJim Jagielski "chatter": chatter, 60*2cb6d6f1SJim Jagielski "spawn_child": spawn_child, 61*2cb6d6f1SJim Jagielski "die139": lambda: os._exit(139), 62*2cb6d6f1SJim Jagielski "office-gone": lambda: (_ for _ in ()).throw(Fail("office_dead", "DisposedException: cannot get value ServiceManager")), 63*2cb6d6f1SJim Jagielski} 64*2cb6d6f1SJim Jagielski 65*2cb6d6f1SJim Jagielskiif mode == "good": 66*2cb6d6f1SJim Jagielski serve(OPS) 67*2cb6d6f1SJim Jagielskielif mode == "silent": 68*2cb6d6f1SJim Jagielski time.sleep(120) 69*2cb6d6f1SJim Jagielskielif mode == "garbage-hello": 70*2cb6d6f1SJim Jagielski print("this is not json", flush=True) 71*2cb6d6f1SJim Jagielski time.sleep(120) 72*2cb6d6f1SJim Jagielskielif mode == "wrong-protocol": 73*2cb6d6f1SJim Jagielski hello(99) 74*2cb6d6f1SJim Jagielski time.sleep(120) 75*2cb6d6f1SJim Jagielskielif mode == "exit-before-hello": 76*2cb6d6f1SJim Jagielski os._exit(3) 77*2cb6d6f1SJim Jagielskielse: 78*2cb6d6f1SJim Jagielski hello() 79*2cb6d6f1SJim Jagielski req = request() 80*2cb6d6f1SJim Jagielski if mode == "crash139": 81*2cb6d6f1SJim Jagielski os._exit(139) 82*2cb6d6f1SJim Jagielski elif mode == "sigkill": 83*2cb6d6f1SJim Jagielski os.kill(os.getpid(), signal.SIGKILL) 84*2cb6d6f1SJim Jagielski elif mode == "stderr-then-crash": 85*2cb6d6f1SJim Jagielski print("fatal: the office bridge fell over", file=sys.stderr, flush=True) 86*2cb6d6f1SJim Jagielski os._exit(7) 87*2cb6d6f1SJim Jagielski elif mode == "garbage-reply": 88*2cb6d6f1SJim Jagielski print("garbage", flush=True) 89*2cb6d6f1SJim Jagielski elif mode == "not-an-object": 90*2cb6d6f1SJim Jagielski print("[1, 2, 3]", flush=True) 91*2cb6d6f1SJim Jagielski elif mode == "wrong-id": 92*2cb6d6f1SJim Jagielski print(json.dumps({"id": req["id"] + 100, "ok": True, "result": {}}), flush=True) 93*2cb6d6f1SJim Jagielski elif mode == "binary-reply": 94*2cb6d6f1SJim Jagielski sys.stdout.buffer.write(b"\xff\xfe\x00\n") 95*2cb6d6f1SJim Jagielski sys.stdout.buffer.flush() 96*2cb6d6f1SJim Jagielski elif mode == "hang": 97*2cb6d6f1SJim Jagielski pass 98*2cb6d6f1SJim Jagielski else: 99*2cb6d6f1SJim Jagielski sys.exit("unknown mode " + mode) 100*2cb6d6f1SJim Jagielski time.sleep(120) 101