def test_h3_quic_with_custom_upstream_bind_configuration(
        quic_test_server_fixture):
    """Test http3 quic with a custom upstream bind configuration.

  Runs the CLI configured to use HTTP/3 Quic against our test server, and sanity
  checks statistics from both client and server. Sets custom address to bind
  upstream requests to.
  """
    address = quic_test_server_fixture.server_ip
    upstream_bind_config = f"{{source_address:{{address:\"{address}\",port_value:0}}}}"

    parsed_json, _ = quic_test_server_fixture.runNighthawkClient([
        "--protocol http3",
        quic_test_server_fixture.getTestServerRootUri(),
        "--rps",
        "100",
        "--duration",
        "100",
        "--termination-predicate",
        "benchmark.http_2xx:24",
        "--max-active-requests",
        "1",
        # Envoy doesn't support disabling certificate verification on Quic
        # connections, so the host in our requests has to match the hostname in
        # the leaf certificate.
        "--request-header",
        "Host:www.lyft.com",
        "--upstream-bind-config %s" % upstream_bind_config
    ])
    counters = quic_test_server_fixture.getNighthawkCounterMapFromJson(
        parsed_json)
    asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
    asserts.assertCounterEqual(counters, "upstream_cx_http3_total", 1)
def test_https_h2_sni(https_test_server_fixture):
  """Tests that SNI indication works on https/h1."""
  # Verify success when we set the right host
  parsed_json, _ = https_test_server_fixture.runNighthawkClient([
      https_test_server_fixture.getTestServerRootUri(), "--rps", "100", "--duration", "100",
      "--termination-predicate", "benchmark.http_2xx:2", "--request-header", ":authority: sni.com",
      "--h2"
  ])
  counters = https_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterGreaterEqual(counters, "benchmark.http_2xx", 1)
  asserts.assertCounterGreaterEqual(counters, "upstream_cx_http2_total", 1)
  asserts.assertCounterEqual(counters, "ssl.handshake", 1)

  # Verify success when we set the right host
  parsed_json, _ = https_test_server_fixture.runNighthawkClient([
      https_test_server_fixture.getTestServerRootUri(), "--rps", "100", "--duration", "100",
      "--termination-predicate", "benchmark.http_2xx:2", "--request-header", "host: sni.com", "--h2"
  ])
  counters = https_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterGreaterEqual(counters, "benchmark.http_2xx", 1)
  asserts.assertCounterGreaterEqual(counters, "upstream_cx_http2_total", 1)
  asserts.assertCounterEqual(counters, "ssl.handshake", 1)

  # Verify failure when we set no host (will get plain http)
  parsed_json, _ = https_test_server_fixture.runNighthawkClient([
      https_test_server_fixture.getTestServerRootUri(), "--rps", "100", "--duration", "100", "--h2"
  ],
                                                                expect_failure=True)

  # Verify failure when we provide both host and :authority: (will get plain http)
  parsed_json, _ = https_test_server_fixture.runNighthawkClient([
      https_test_server_fixture.getTestServerRootUri(), "--rps", "100", "--duration", "100", "--h2",
      "--request-header", "host: sni.com", "--request-header", ":authority: sni.com"
  ],
                                                                expect_failure=True)
Beispiel #3
0
def _run_with_number_of_connections(fixture,
                                    number_of_connections,
                                    expected_connections=-1,
                                    max_pending_requests=0,
                                    requests_per_connection=1024 * 1024,
                                    rps=100,
                                    run_test_expectation=True,
                                    h2=False):
    if expected_connections == -1:
        expected_connections = number_of_connections
    # We add a delay to responses to make sure connections are needed, as the pool creates connections on-demand.
    args = [
        fixture.getTestServerRootUri(), "--rps",
        str(rps), "--duration", "2", "--request-header",
        "x-envoy-fault-delay-request:500", "--max-pending-requests",
        str(max_pending_requests), "--max-requests-per-connection",
        str(requests_per_connection), "--connections",
        str(number_of_connections)
    ]
    if h2:
        args.append("--h2")
    parsed_json, _ = fixture.runNighthawkClient(args)
    counters = fixture.getNighthawkCounterMapFromJson(parsed_json)
    if run_test_expectation:
        asserts.assertCounterEqual(counters, "upstream_cx_total",
                                   expected_connections)
    return counters
def test_http_request_release_timing(http_test_server_fixture,
                                     qps_parameterization_fixture,
                                     duration_parameterization_fixture):
    """Test latency-sample-, query- and reply- counts in various configurations."""
    for concurrency in [1, 2]:
        parsed_json, _ = http_test_server_fixture.runNighthawkClient([
            http_test_server_fixture.getTestServerRootUri(), "--duration",
            str(duration_parameterization_fixture), "--rps",
            str(qps_parameterization_fixture), "--concurrency",
            str(concurrency)
        ])

        total_requests = qps_parameterization_fixture * concurrency * duration_parameterization_fixture
        global_histograms = http_test_server_fixture.getNighthawkGlobalHistogramsbyIdFromJson(
            parsed_json)
        counters = http_test_server_fixture.getNighthawkCounterMapFromJson(
            parsed_json)
        asserts.assertEqual(
            int(global_histograms["benchmark_http_client.request_to_response"]
                ["count"]), total_requests)
        asserts.assertEqual(
            int(global_histograms["benchmark_http_client.queue_to_connect"]
                ["count"]), total_requests)
        asserts.assertEqual(
            int(global_histograms["benchmark_http_client.latency_2xx"]
                ["count"]), total_requests)

        asserts.assertCounterEqual(counters, "benchmark.http_2xx",
                                   (total_requests))
def test_http_h1_mini_stress_test_without_client_side_queueing(http_test_server_fixture):
  """Run a max rps test with the h1 pool against our test server, with no client-side queueing."""
  counters = _mini_stress_test(http_test_server_fixture, [
      http_test_server_fixture.getTestServerRootUri(), "--rps", "999999", "--connections", "1",
      "--duration", "100", "--termination-predicate", "benchmark.http_2xx:99"
  ])
  asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 1)
  asserts.assertNotIn("upstream_cx_overflow", counters)
def test_http_h2_mini_stress_test_with_client_side_queueing(http_test_server_fixture):
  """Run a max rps test with the h2 pool against our test server, using a small client-side queue."""
  counters = _mini_stress_test(http_test_server_fixture, [
      http_test_server_fixture.getTestServerRootUri(), "--rps", "999999", "--max-pending-requests",
      "10", "--h2", "--max-active-requests", "1", "--connections", "1", "--duration", "100",
      "--termination-predicate", "benchmark.http_2xx:99", "--simple-warmup"
  ])
  asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 1)
  asserts.assertCounterGreaterEqual(counters, "upstream_rq_pending_overflow", 10)
def test_nighthawk_client_v2_api_explicitly_set(http_test_server_fixture):
  """Test that the v2 api works when requested to."""
  parsed_json, _ = http_test_server_fixture.runNighthawkClient([
      http_test_server_fixture.getTestServerRootUri(), "--duration", "100",
      "--termination-predicate", "benchmark.pool_connection_failure:0", "--failure-predicate",
      "foo:1", "--allow-envoy-deprecated-v2-api", "--transport-socket",
      "{name:\"envoy.transport_sockets.tls\",typed_config:{\"@type\":\"type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext\",\"common_tls_context\":{}}}"
  ])

  counters = http_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterEqual(counters, "benchmark.pool_connection_failure", 1)
def test_nighthawk_test_server_envoy_deprecated_v2_api(
    http_test_server_fixture_envoy_deprecated_v2_api):
  """Test that the v2 configuration works for the test server."""
  parsed_json, _ = http_test_server_fixture_envoy_deprecated_v2_api.runNighthawkClient([
      http_test_server_fixture_envoy_deprecated_v2_api.getTestServerRootUri(), "--duration", "100",
      "--termination-predicate", "benchmark.http_2xx:24"
  ])

  counters = http_test_server_fixture_envoy_deprecated_v2_api.getNighthawkCounterMapFromJson(
      parsed_json)
  asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
def test_http_h1_failure_predicate(http_test_server_fixture):
  """Test with a failure predicate.

  Should result in failing execution, with 10 successfull requests.
  """
  parsed_json, _ = http_test_server_fixture.runNighthawkClient([
      http_test_server_fixture.getTestServerRootUri(), "--duration", "5", "--rps", "500",
      "--connections", "1", "--failure-predicate", "benchmark.http_2xx:0"
  ],
                                                               expect_failure=True)
  counters = http_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterEqual(counters, "benchmark.http_2xx", 1)
def test_http_h1_termination_predicate(http_test_server_fixture):
  """Test with a termination predicate.

  Should result in successful execution, with 10 successful requests.
  We would expect 25 based on rps and duration.
  """
  parsed_json, _ = http_test_server_fixture.runNighthawkClient([
      http_test_server_fixture.getTestServerRootUri(), "--duration", "5", "--rps", "500",
      "--connections", "1", "--termination-predicate", "benchmark.http_2xx:9"
  ])
  counters = http_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterEqual(counters, "benchmark.http_2xx", 10)
def test_http_concurrency(http_test_server_fixture):
  """Test that concurrency acts like a multiplier."""
  parsed_json, _ = http_test_server_fixture.runNighthawkClient([
      "--concurrency 4 --rps 100 --connections 1", "--duration", "100", "--termination-predicate",
      "benchmark.http_2xx:24",
      http_test_server_fixture.getTestServerRootUri()
  ])
  counters = http_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)

  # Quite a loose expectation, but this may fluctuate depending on server load.
  # Ideally we'd see 4 workers * 5 rps * 5s = 100 requests total
  asserts.assertCounterEqual(counters, "benchmark.http_2xx", 100)
  asserts.assertCounterEqual(counters, "upstream_cx_http1_total", 4)
def test_https_prefetching(https_test_server_fixture):
  """Test we prefetch connections.

  We test for 1 second at 1 rps, which should
  result in 1 connection max without prefetching. However, we specify 50 connections
  and the prefetching flag, so we ought to see 50 http1 connections created.
  """
  parsed_json, _ = https_test_server_fixture.runNighthawkClient([
      "--duration 1", "--rps 1", "--prefetch-connections", "--connections 50",
      https_test_server_fixture.getTestServerRootUri()
  ])
  counters = https_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterEqual(counters, "upstream_cx_http1_total", 50)
def test_http_h1(http_test_server_fixture):
    """Test http1 over plain http.

  Runs the CLI configured to use plain HTTP/1 against our test server, and sanity
  checks statistics from both client and server.
  """
    parsed_json, _ = http_test_server_fixture.runNighthawkClient([
        http_test_server_fixture.getTestServerRootUri(), "--duration", "100",
        "--termination-predicate", "benchmark.http_2xx:24"
    ])
    counters = http_test_server_fixture.getNighthawkCounterMapFromJson(
        parsed_json)
    asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
    asserts.assertCounterEqual(counters, "upstream_cx_rx_bytes_total", 3400)
    # It is possible that the # of upstream_cx > # of backend connections for H1
    # as new connections will spawn if the existing clients cannot keep up with the RPS.
    asserts.assertCounterGreaterEqual(counters, "upstream_cx_http1_total", 1)
    asserts.assertCounterGreaterEqual(counters, "upstream_cx_total", 1)
    asserts.assertCounterGreaterEqual(counters, "upstream_cx_tx_bytes_total",
                                      500)
    asserts.assertCounterGreaterEqual(counters, "upstream_rq_pending_total", 1)
    asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
    asserts.assertCounterEqual(counters, "default.total_match_count", 1)

    global_histograms = http_test_server_fixture.getNighthawkGlobalHistogramsbyIdFromJson(
        parsed_json)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["count"]), 25)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["count"]), 25)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_mean"]), 10)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_mean"]), 97)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_min"]), 10)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_min"]), 97)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_max"]), 10)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_max"]), 97)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_pstdev"]), 0)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_pstdev"]), 0)

    asserts.assertGreaterEqual(len(counters), 12)
def test_cancellation_with_infinite_duration(http_test_server_fixture):
  """Test that we can use signals to cancel execution."""
  args = [
      http_test_server_fixture.nighthawk_client_path, "--concurrency", "2",
      http_test_server_fixture.getTestServerRootUri(), "--no-duration", "--output-format", "json"
  ]
  client_process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  Thread(target=(lambda: _send_sigterm(client_process))).start()
  stdout, stderr = client_process.communicate()
  client_process.wait()
  output = stdout.decode('utf-8')
  asserts.assertEqual(client_process.returncode, 0)
  parsed_json = json.loads(output)
  counters = http_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterEqual(counters, "graceful_stop_requested", 2)
  asserts.assertCounterGreaterEqual(counters, "benchmark.http_2xx", 1)
def test_http_concurrency(http_test_server_fixture):
  """Test that concurrency acts like a multiplier."""
  parsed_json, _ = http_test_server_fixture.runNighthawkClient([
      "--concurrency 4 --rps 100 --connections 1", "--duration", "100", "--termination-predicate",
      "benchmark.http_2xx:24",
      http_test_server_fixture.getTestServerRootUri()
  ])
  counters = http_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)

  # Quite a loose expectation, but this may fluctuate depending on server load.
  # Ideally we'd see 4 workers * 5 rps * 5s = 100 requests total
  asserts.assertCounterEqual(counters, "benchmark.http_2xx", 100)
  # Assert that we at least have 1 connection for each event loop (1*4). It is possible that the # of
  # upstream_cx > # of backend connections for H1 as new connections will spawn if the existing clients
  # cannot keep up with the RPS.
  asserts.assertCounterGreaterEqual(counters, "upstream_cx_http1_total", 4)
def _mini_stress_test(fixture, args):
    # run a test with more rps then we can handle, and a very small client-side queue.
    # we should observe both lots of successfull requests as well as time spend in blocking mode.,
    parsed_json, _ = fixture.runNighthawkClient(args)
    counters = fixture.getNighthawkCounterMapFromJson(parsed_json)
    # We set a reasonably low expectation of 100 requests. We set it low, because we want this
    # test to succeed on a reasonable share of setups (hopefully practically all).
    MIN_EXPECTED_REQUESTS = 100
    asserts.assertCounterEqual(counters, "benchmark.http_2xx",
                               MIN_EXPECTED_REQUESTS)
    if "--h2" in args:
        asserts.assertCounterEqual(counters, "upstream_cx_http2_total", 1)
    else:
        asserts.assertCounterEqual(counters, "upstream_cx_http1_total", 1)
    global_histograms = fixture.getNighthawkGlobalHistogramsbyIdFromJson(
        parsed_json)

    if "--open-loop" in args:
        asserts.assertEqual(
            int(global_histograms["sequencer.blocking"]["count"]), 0)
    else:
        asserts.assertGreaterEqual(
            int(global_histograms["sequencer.blocking"]["count"]), 1)

    asserts.assertGreaterEqual(
        int(global_histograms["benchmark_http_client.request_to_response"]
            ["count"]), 1)
    asserts.assertGreaterEqual(
        int(global_histograms["benchmark_http_client.latency_2xx"]["count"]),
        1)
    return counters
def test_multiple_backends_https_h1(multi_https_test_server_fixture):
  """Test that we can load-test multiple backends on https.

  Runs the CLI configured to use HTTP/1 with TLS against multiple test servers, and sanity
  checks statistics from both client and server.
  """
  nighthawk_client_args = [
      "--multi-target-use-https", "--multi-target-path", "/", "--duration", "100",
      "--termination-predicate", "benchmark.http_2xx:24"
  ]
  for uri in multi_https_test_server_fixture.getAllTestServerRootUris():
    nighthawk_client_args.append("--multi-target-endpoint")
    nighthawk_client_args.append(uri.replace("https://", "").replace("/", ""))

  parsed_json, stderr = multi_https_test_server_fixture.runNighthawkClient(nighthawk_client_args)

  counters = multi_https_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
  asserts.assertCounterGreater(counters, "upstream_cx_rx_bytes_total", 0)
  # Assert that we at least have 1 connection per backend. It is possible that
  # the # of upstream_cx > # of backend connections for H1 as new connections
  # will spawn if the existing clients cannot keep up with the RPS.
  asserts.assertCounterGreaterEqual(counters, "upstream_cx_http1_total", 3)
  asserts.assertCounterGreaterEqual(counters, "upstream_cx_total", 3)
  asserts.assertCounterGreaterEqual(counters, "upstream_rq_pending_total", 3)
  asserts.assertCounterGreater(counters, "upstream_cx_tx_bytes_total", 0)
  asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
  asserts.assertCounterEqual(counters, "default.total_match_count", 3)
  for parsed_server_json in multi_https_test_server_fixture.getAllTestServerStatisticsJsons():
    single_2xx = multi_https_test_server_fixture.getServerStatFromJson(
        parsed_server_json, "http.ingress_http.downstream_rq_2xx")
    # Confirm that each backend receives some traffic
    asserts.assertGreaterEqual(single_2xx, 1)
Beispiel #18
0
def _run_benchmark(fixture,
                   rps=1000,
                   duration=30,
                   max_connections=1,
                   max_active_requests=100,
                   request_body_size=0,
                   response_size=1024,
                   concurrency=1):
    if hasattr(fixture, "proxy_server"):
        assert (fixture.proxy_server.enableCpuProfiler())
    assert (fixture.test_server.enableCpuProfiler())
    args = [
        fixture.getTestServerRootUri(), "--rps",
        str(rps), "--duration",
        str(duration), "--connections",
        str(max_connections), "--max-active-requests",
        str(max_active_requests), "--concurrency",
        str(concurrency), "--request-header",
        "x-nighthawk-test-server-config:{response_body_size:%s}" %
        response_size, "--experimental-h1-connection-reuse-strategy", "lru",
        "--prefetch-connections"
    ]
    if request_body_size > 0:
        args.append("--request-body-size")
        args.append(str(request_body_size))

    parsed_json, _ = fixture.runNighthawkClient(args)
    counters = fixture.getNighthawkCounterMapFromJson(parsed_json)
    response_count = counters["benchmark.http_2xx"]
    request_count = counters["upstream_rq_total"]
    connection_counter = "upstream_cx_http1_total"

    # Some arbitrary sanity checks
    asserts.assertCounterGreaterEqual(counters, "benchmark.http_2xx",
                                      (concurrency * rps * duration) * 0.99)
    asserts.assertGreater(counters["upstream_cx_rx_bytes_total"],
                          response_count * response_size)
    asserts.assertGreater(counters["upstream_cx_tx_bytes_total"],
                          request_count * request_body_size)
    asserts.assertCounterEqual(counters, connection_counter,
                               concurrency * max_connections)

    # Could potentially set thresholds on acceptable latency here.

    # dump human readable output to logs
    json_as_string = json.dumps(parsed_json)
    human_output = fixture.transformNighthawkJson(json_as_string, "human")
    logging.info(human_output)

    with open(os.path.join(fixture.test_server.tmpdir, "nighthawk-human.txt"),
              "w") as f:
        f.write(human_output)
    with open(os.path.join(fixture.test_server.tmpdir, "nighthawk.json"),
              "w") as f:
        f.write(json_as_string)
    with open(os.path.join(fixture.test_server.tmpdir, "nighthawk.yaml"),
              "w") as f:
        f.write(fixture.transformNighthawkJson(json_as_string, "yaml"))
    with open(os.path.join(fixture.test_server.tmpdir, "fortio.json"),
              "w") as f:
        f.write(fixture.transformNighthawkJson(json_as_string, "fortio"))
    with open(os.path.join(fixture.test_server.tmpdir, "server_version.txt"),
              "w") as f:
        f.write(fixture.test_server.getCliVersionString())
    if hasattr(fixture, "proxy_server"):
        with open(
                os.path.join(fixture.test_server.tmpdir, "proxy_version.txt"),
                "w") as f:
            f.write(fixture.proxy_server.getCliVersionString())
    r = runfiles.Create()
    copyfile(
        r.Rlocation("nighthawk/benchmarks/test/templates/simple_plot.html"),
        os.path.join(fixture.test_server.tmpdir, "simple_plot.html"))
def test_multiple_backends_https_h1(multi_https_test_server_fixture):
    """Test that we can load-test multiple backends on https.

  Runs the CLI configured to use HTTP/1 with TLS against multiple test servers, and sanity
  checks statistics from both client and server.
  """
    nighthawk_client_args = [
        "--multi-target-use-https", "--multi-target-path", "/", "--duration",
        "100", "--termination-predicate", "benchmark.http_2xx:24"
    ]
    for uri in multi_https_test_server_fixture.getAllTestServerRootUris():
        nighthawk_client_args.append("--multi-target-endpoint")
        nighthawk_client_args.append(
            uri.replace("https://", "").replace("/", ""))

    parsed_json, stderr = multi_https_test_server_fixture.runNighthawkClient(
        nighthawk_client_args)

    counters = multi_https_test_server_fixture.getNighthawkCounterMapFromJson(
        parsed_json)
    asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
    asserts.assertCounterEqual(counters, "upstream_cx_http1_total", 3)
    asserts.assertCounterGreater(counters, "upstream_cx_rx_bytes_total", 0)
    asserts.assertCounterEqual(counters, "upstream_cx_total", 3)
    asserts.assertCounterGreater(counters, "upstream_cx_tx_bytes_total", 0)
    asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 3)
    asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
    asserts.assertCounterEqual(counters, "default.total_match_count", 3)
    total_2xx = 0
    for parsed_server_json in multi_https_test_server_fixture.getAllTestServerStatisticsJsons(
    ):
        single_2xx = multi_https_test_server_fixture.getServerStatFromJson(
            parsed_server_json, "http.ingress_http.downstream_rq_2xx")
        asserts.assertBetweenInclusive(single_2xx, 8, 9)
        total_2xx += single_2xx
    asserts.assertBetweenInclusive(total_2xx, 24, 25)
def test_https_h2(https_test_server_fixture):
    """Test http2 over https.

  Runs the CLI configured to use HTTP/2 (using https) against our test server, and sanity
  checks statistics from both client and server.
  """
    parsed_json, _ = https_test_server_fixture.runNighthawkClient([
        "--h2",
        https_test_server_fixture.getTestServerRootUri(), "--rps", "100",
        "--duration", "100", "--termination-predicate",
        "benchmark.http_2xx:24", "--max-active-requests", "1"
    ])
    counters = https_test_server_fixture.getNighthawkCounterMapFromJson(
        parsed_json)
    asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
    asserts.assertCounterEqual(counters, "upstream_cx_http2_total", 1)
    # Through emperical observation, 1030 has been determined to be the minimum of bytes
    # we can expect to have received when execution has stopped.
    asserts.assertCounterGreaterEqual(counters, "upstream_cx_rx_bytes_total",
                                      1030)
    asserts.assertCounterEqual(counters, "upstream_cx_total", 1)
    asserts.assertCounterGreaterEqual(counters, "upstream_cx_tx_bytes_total",
                                      403)
    asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 1)
    asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
    asserts.assertCounterEqual(counters,
                               "ssl.ciphers.ECDHE-RSA-AES128-GCM-SHA256", 1)
    asserts.assertCounterEqual(counters, "ssl.curves.X25519", 1)
    asserts.assertCounterEqual(counters, "ssl.handshake", 1)
    asserts.assertCounterEqual(counters, "ssl.sigalgs.rsa_pss_rsae_sha256", 1)
    asserts.assertCounterEqual(counters, "ssl.versions.TLSv1.2", 1)
    asserts.assertCounterEqual(counters, "default.total_match_count", 1)
    asserts.assertEqual(len(counters), 17)
def test_https_h1(https_test_server_fixture):
    """Test h1 over https.

  Runs the CLI configured to use HTTP/1 over https against our test server, and sanity
  checks statistics from both client and server.
  """
    parsed_json, _ = https_test_server_fixture.runNighthawkClient([
        https_test_server_fixture.getTestServerRootUri(), "--connections", "1",
        "--rps", "100", "--duration", "100", "--termination-predicate",
        "benchmark.http_2xx:24"
    ])
    counters = https_test_server_fixture.getNighthawkCounterMapFromJson(
        parsed_json)
    asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
    asserts.assertCounterEqual(counters, "upstream_cx_http1_total", 1)
    asserts.assertCounterEqual(counters, "upstream_cx_rx_bytes_total", 3400)
    asserts.assertCounterEqual(counters, "upstream_cx_total", 1)
    asserts.assertCounterEqual(
        counters, "upstream_cx_tx_bytes_total", 1375
        if https_test_server_fixture.ip_version == IpVersion.IPV6 else 1450)
    asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 1)
    asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
    asserts.assertCounterEqual(counters,
                               "ssl.ciphers.ECDHE-RSA-AES128-GCM-SHA256", 1)
    asserts.assertCounterEqual(counters, "ssl.curves.X25519", 1)
    asserts.assertCounterEqual(counters, "ssl.handshake", 1)
    asserts.assertCounterEqual(counters, "ssl.sigalgs.rsa_pss_rsae_sha256", 1)
    asserts.assertCounterEqual(counters, "ssl.versions.TLSv1.2", 1)
    asserts.assertCounterEqual(counters, "default.total_match_count", 1)
    asserts.assertEqual(len(counters), 17)

    server_stats = https_test_server_fixture.getTestServerStatisticsJson()
    asserts.assertEqual(
        https_test_server_fixture.getServerStatFromJson(
            server_stats, "http.ingress_http.downstream_rq_2xx"), 25)
def test_http_h2(http_test_server_fixture):
    """Test h2 over plain http.

  Runs the CLI configured to use h2c against our test server, and sanity
  checks statistics from both client and server.
  """
    parsed_json, _ = http_test_server_fixture.runNighthawkClient([
        "--h2",
        http_test_server_fixture.getTestServerRootUri(),
        "--max-active-requests", "1", "--duration", "100",
        "--termination-predicate", "benchmark.http_2xx:24", "--rps", "100"
    ])
    counters = http_test_server_fixture.getNighthawkCounterMapFromJson(
        parsed_json)
    asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
    asserts.assertCounterEqual(counters, "upstream_cx_http2_total", 1)
    asserts.assertCounterGreaterEqual(counters, "upstream_cx_rx_bytes_total",
                                      1030)
    asserts.assertCounterEqual(counters, "upstream_cx_total", 1)
    asserts.assertCounterGreaterEqual(counters, "upstream_cx_tx_bytes_total",
                                      403)
    asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 1)
    asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
    asserts.assertCounterEqual(counters, "default.total_match_count", 1)
    asserts.assertEqual(len(counters), 12)
def test_http_h1(http_test_server_fixture):
    """Test http1 over plain http.

  Runs the CLI configured to use plain HTTP/1 against our test server, and sanity
  checks statistics from both client and server.
  """
    parsed_json, _ = http_test_server_fixture.runNighthawkClient([
        http_test_server_fixture.getTestServerRootUri(), "--duration", "100",
        "--termination-predicate", "benchmark.http_2xx:24"
    ])
    counters = http_test_server_fixture.getNighthawkCounterMapFromJson(
        parsed_json)
    asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
    asserts.assertCounterEqual(counters, "upstream_cx_http1_total", 1)
    asserts.assertCounterEqual(counters, "upstream_cx_rx_bytes_total", 3400)
    asserts.assertCounterEqual(counters, "upstream_cx_total", 1)
    asserts.assertCounterEqual(
        counters, "upstream_cx_tx_bytes_total", 1375
        if http_test_server_fixture.ip_version == IpVersion.IPV6 else 1450)
    asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 1)
    asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
    asserts.assertCounterEqual(counters, "default.total_match_count", 1)

    global_histograms = http_test_server_fixture.getNighthawkGlobalHistogramsbyIdFromJson(
        parsed_json)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["count"]), 25)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["count"]), 25)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_mean"]), 10)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_mean"]), 97)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_min"]), 10)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_min"]), 97)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_max"]), 10)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_max"]), 97)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_body_size"]
            ["raw_pstdev"]), 0)
    asserts.assertEqual(
        int(global_histograms["benchmark_http_client.response_header_size"]
            ["raw_pstdev"]), 0)

    asserts.assertEqual(len(counters), 12)
def test_h3_quic(quic_test_server_fixture):
  """Test http3 quic.

  Runs the CLI configured to use HTTP/3 Quic against our test server, and sanity
  checks statistics from both client and server.
  """
  parsed_json, _ = quic_test_server_fixture.runNighthawkClient([
      "--protocol http3",
      quic_test_server_fixture.getTestServerRootUri(),
      "--rps",
      "100",
      "--duration",
      "100",
      "--termination-predicate",
      "benchmark.http_2xx:24",
      "--max-active-requests",
      "1",
      # Envoy doesn't support disabling certificate verification on Quic
      # connections, so the host in our requests has to match the hostname in
      # the leaf certificate.
      "--request-header",
      "Host:www.lyft.com"
  ])
  counters = quic_test_server_fixture.getNighthawkCounterMapFromJson(parsed_json)
  asserts.assertCounterEqual(counters, "benchmark.http_2xx", 25)
  asserts.assertCounterEqual(counters, "upstream_cx_http3_total", 1)
  asserts.assertCounterEqual(counters, "upstream_cx_total", 1)
  asserts.assertCounterEqual(counters, "upstream_rq_pending_total", 1)
  asserts.assertCounterEqual(counters, "upstream_rq_total", 25)
  asserts.assertCounterEqual(counters, "default.total_match_count", 1)