xref: /trunk/test/aoo-test/tests/harness/fake_worker.py (revision 2cb6d6f119bbe2f78742f1c5c8538cb0d4e72ede)
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