This is an automated email from the ASF dual-hosted git repository.

spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new a671909  test: fuzz with the simple http case (#4815)
a671909 is described below

commit a671909576ae98f697df8f225124c0b09989cdb6
Author: 罗泽轩 <[email protected]>
AuthorDate: Tue Aug 17 11:58:30 2021 +0800

    test: fuzz with the simple http case (#4815)
---
 .github/workflows/fuzzing-ci.yaml |   3 +-
 t/fuzzing/public.py               |  16 +++--
 t/fuzzing/simple_http.py          | 121 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/fuzzing-ci.yaml 
b/.github/workflows/fuzzing-ci.yaml
index 282eacd..71eaf8b 100644
--- a/.github/workflows/fuzzing-ci.yaml
+++ b/.github/workflows/fuzzing-ci.yaml
@@ -79,6 +79,7 @@ jobs:
       run: |
         python $PWD/t/fuzzing/vars_route_test.py
 
-    - name: run client abort test
+    - name: run check leak test
       run: |
         python $PWD/t/fuzzing/client_abort.py
+        python $PWD/t/fuzzing/simple_http.py
diff --git a/t/fuzzing/public.py b/t/fuzzing/public.py
index 4d67baf..500b3d3 100644
--- a/t/fuzzing/public.py
+++ b/t/fuzzing/public.py
@@ -88,29 +88,35 @@ def gc():
     conn.request("POST", "/v1/gc")
     conn.close()
 
+def leak_count():
+    return int(os.environ.get("APISIX_FUZZING_LEAK_COUNT") or 100)
+
+LEAK_COUNT = leak_count()
+
 def check_leak(f):
     @wraps(f)
     def wrapper(*args, **kwds):
-        leak_count = 100
+        global LEAK_COUNT
 
         samples = []
-        for i in range(leak_count):
+        for i in range(LEAK_COUNT):
             f(*args, **kwds)
             gc()
             samples.append(sum_memory())
         count = 0
-        for i in range(1, leak_count):
+        for i in range(1, LEAK_COUNT):
             if samples[i - 1] < samples[i]:
                 count += 1
         print(samples)
         sloped = get_linear_regression_sloped(samples)
         print(sloped)
-        print(count / leak_count)
+        print(count / LEAK_COUNT)
 
         if os.environ.get("CI"): # CI is not stable
             return
 
-        if sloped > 1000 and (count / leak_count) > 0.1:
+        # the threshold is chosen so that we can find leaking a table per 
request
+        if sloped > 10000 and (count / LEAK_COUNT) > 0.2:
             raise AssertionError("memory leak")
 
     return wrapper
diff --git a/t/fuzzing/simple_http.py b/t/fuzzing/simple_http.py
new file mode 100755
index 0000000..f2d2099
--- /dev/null
+++ b/t/fuzzing/simple_http.py
@@ -0,0 +1,121 @@
+#! /usr/bin/env python
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file provides a fuzzing test with most common plugins via plain HTTP 
request
+import http.client
+import json
+import random
+import threading
+from public import check_leak, LEAK_COUNT, run_test
+
+
+REQ_PER_THREAD = 50
+THREADS_NUM = 10
+TOTOL_ROUTES = 50
+
+
+def create_route():
+    conf = json.dumps({
+        "username": "jack",
+        "plugins": {
+            "jwt-auth": {
+                "key": "user-key",
+                "secret": "my-secret-key"
+            }
+        }
+    })
+    conn = http.client.HTTPConnection("127.0.0.1", port=9080)
+    conn.request("PUT", "/apisix/admin/consumers", conf,
+            headers={
+                "X-API-KEY":"edd1c9f034335f136f87ad84b625c8f1",
+            })
+    response = conn.getresponse()
+    assert response.status <= 300, response.read()
+
+    for i in range(TOTOL_ROUTES):
+        conn = http.client.HTTPConnection("127.0.0.1", port=9080)
+        i = str(i)
+        conf = json.dumps({
+            "uri": "/*",
+            "host": "test" + i + ".com",
+            "plugins": {
+                "limit-count": {
+                    "count": LEAK_COUNT * REQ_PER_THREAD * THREADS_NUM,
+                    "time_window": 3600,
+                },
+                "jwt-auth": {
+                },
+                "proxy-rewrite": {
+                    "uri": "/" + i,
+                    "headers": {
+                        "X-APISIX-Route": "apisix-" + i
+                    }
+                },
+                "response-rewrite": {
+                    "headers": {
+                        "X-APISIX-Route": "$http_x_apisix_route"
+                    }
+                },
+            },
+            "upstream": {
+                "nodes": {
+                    "127.0.0.1:6666": 1
+                },
+                "type": "roundrobin"
+            },
+        })
+
+        conn.request("PUT", "/apisix/admin/routes/" + i, conf,
+                headers={
+                    "X-API-KEY":"edd1c9f034335f136f87ad84b625c8f1",
+                })
+        response = conn.getresponse()
+        assert response.status <= 300, response.read()
+
+def req():
+    jwt_token = ("Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."+
+        "eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTg3OTMxODU0MX0."+
+        "fNtFJnNmJgzbiYmGB0Yjvm-l6A6M4jRV1l4mnVFSYjs")
+    route_id = str(random.randrange(TOTOL_ROUTES))
+    conn = http.client.HTTPConnection("127.0.0.1", port=9080)
+    conn.request("GET", "/",
+            headers={
+                "Host":"test" + route_id + ".com",
+                "Authorization":jwt_token,
+            })
+    response = conn.getresponse()
+    assert response.status == 200, response.read()
+    hdr = response.headers["X-APISIX-Route"]
+    assert hdr == "apisix-" + route_id, hdr
+
+def run_in_thread():
+    for i in range(REQ_PER_THREAD):
+        req()
+
+@check_leak
+def run():
+    th = [threading.Thread(target=run_in_thread) for i in range(THREADS_NUM)]
+    for t in th:
+        t.start()
+    for t in th:
+        t.join()
+
+
+if __name__ == "__main__":
+    run_test(create_route, run)

Reply via email to