From b04ac9209718cebd08179dd425c0e1579412a28d Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 8 Sep 2021 18:53:48 -0500 Subject: [PATCH] [Heartbeat] Move JSON tests from python->go (#27816) --- heartbeat/hbtest/hbtestutil.go | 9 ++ heartbeat/monitors/active/http/http_test.go | 106 ++++++++++++++++++++ heartbeat/tests/system/test_monitor.py | 82 --------------- 3 files changed, 115 insertions(+), 82 deletions(-) diff --git a/heartbeat/hbtest/hbtestutil.go b/heartbeat/hbtest/hbtestutil.go index ec802079fbc8..80753294d8ec 100644 --- a/heartbeat/hbtest/hbtestutil.go +++ b/heartbeat/hbtest/hbtestutil.go @@ -83,6 +83,15 @@ func SizedResponseHandler(bytes int) http.HandlerFunc { ) } +func CustomResponseHandler(body []byte, status int) http.HandlerFunc { + return http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(status) + w.Write(body) + }, + ) +} + // RedirectHandler redirects the paths at the keys in the redirectingPaths map to the locations in their values. // For paths not in the redirectingPaths map it returns a 200 response with the given body. func RedirectHandler(redirectingPaths map[string]string, body string) http.HandlerFunc { diff --git a/heartbeat/monitors/active/http/http_test.go b/heartbeat/monitors/active/http/http_test.go index 4e6f67dec973..48b37b74d89b 100644 --- a/heartbeat/monitors/active/http/http_test.go +++ b/heartbeat/monitors/active/http/http_test.go @@ -341,6 +341,112 @@ func TestLargeResponse(t *testing.T) { ) } +func TestJsonBody(t *testing.T) { + type testCase struct { + name string + responseBody string + condition common.MapStr + expectedErrMsg string + expectedContentType string + } + + testCases := []testCase{ + { + "simple match", + "{\"foo\": \"bar\"}", + common.MapStr{ + "equals": common.MapStr{"foo": "bar"}, + }, + "", + "application/json", + }, + { + "mismatch", + "{\"foo\": \"bar\"}", + common.MapStr{ + "equals": common.MapStr{"baz": "bot"}, + }, + "JSON body did not match", + "application/json", + }, + { + "invalid json", + "notjson", + common.MapStr{ + "equals": common.MapStr{"foo": "bar"}, + }, + "could not parse JSON", + "text/plain; charset=utf-8", + }, + { + "complex type match json", + "{\"number\": 3, \"bool\": true}", + common.MapStr{ + "equals": common.MapStr{"number": 3, "bool": true}, + }, + "", + "application/json", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + server := httptest.NewServer(hbtest.CustomResponseHandler([]byte(tc.responseBody), 200)) + defer server.Close() + + configSrc := map[string]interface{}{ + "hosts": server.URL, + "timeout": "1s", + "response.include_body": "never", + "check.response.json": []common.MapStr{ + { + "description": "myJsonCheck", + "condition": tc.condition, + }, + }, + } + + config, err := common.NewConfigFrom(configSrc) + require.NoError(t, err) + + p, err := create("largeresp", config) + require.NoError(t, err) + + sched, _ := schedule.Parse("@every 1s") + job := wrappers.WrapCommon(p.Jobs, stdfields.StdMonitorFields{ID: "test", Type: "http", Schedule: sched, Timeout: 1})[0] + + event := &beat.Event{} + _, err = job(event) + require.NoError(t, err) + + if tc.expectedErrMsg == "" { + testslike.Test( + t, + lookslike.Strict(lookslike.Compose( + hbtest.BaseChecks("127.0.0.1", "up", "http"), + hbtest.RespondingTCPChecks(), + hbtest.SummaryChecks(1, 0), + respondingHTTPChecks(server.URL, tc.expectedContentType, 200), + )), + event.Fields, + ) + } else { + testslike.Test( + t, + lookslike.Strict(lookslike.Compose( + hbtest.BaseChecks("127.0.0.1", "down", "http"), + hbtest.RespondingTCPChecks(), + hbtest.SummaryChecks(0, 1), + hbtest.ErrorChecks(tc.expectedErrMsg, "validate"), + respondingHTTPChecks(server.URL, tc.expectedContentType, 200), + )), + event.Fields, + ) + } + }) + } +} + func runHTTPSServerCheck( t *testing.T, server *httptest.Server, diff --git a/heartbeat/tests/system/test_monitor.py b/heartbeat/tests/system/test_monitor.py index 4952ab8d2590..b7a1edae5be7 100644 --- a/heartbeat/tests/system/test_monitor.py +++ b/heartbeat/tests/system/test_monitor.py @@ -90,88 +90,6 @@ def test_http_delayed(self): finally: server.shutdown() - @parameterized.expand([ - ("up", '{"foo": {"baz": "bar"}}'), - ("down", '{"foo": "unexpected"}'), - ("down", 'notjson'), - ]) - def test_http_json(self, expected_status, body): - """ - Test JSON response checks - """ - server = self.start_server(body, 200) - try: - self.render_config_template( - monitors=[{ - "type": "http", - "urls": ["http://localhost:{}".format(server.server_port)], - "check_response_json": [{ - "description": "foo equals bar", - "condition": { - "equals": {"foo": {"baz": "bar"}} - } - }] - }] - ) - - try: - proc = self.start_beat() - self.wait_until(lambda: self.log_contains("heartbeat is running")) - - self.wait_until( - lambda: self.output_has(lines=1)) - finally: - proc.check_kill_and_wait() - - self.assert_last_status(expected_status) - if expected_status == "down": - self.assertEqual(self.last_output_line()["http.response.body.content"], body) - if body == "notjson": - self.assertEqual(self.last_output_line()["http.response.mime_type"], "text/plain; charset=utf-8") - else: - self.assertEqual(self.last_output_line()["http.response.mime_type"], "application/json") - else: - assert "http.response.body.content" not in self.last_output_line() - finally: - server.shutdown() - - @parameterized.expand([ - ('{"foo": "bar"}', {"foo": "bar"}), - ('{"foo": true}', {"foo": True},), - ('{"foo": 3}', {"foo": 3},), - ]) - def test_json_simple_comparisons(self, body, comparison): - """ - Test JSON response with simple straight-forward comparisons - """ - server = self.start_server(body, 200) - try: - self.render_config_template( - monitors=[{ - "type": "http", - "urls": ["http://localhost:{}".format(server.server_port)], - "check_response_json": [{ - "description": body, - "condition": { - "equals": comparison - } - }] - }] - ) - - try: - proc = self.start_beat() - self.wait_until(lambda: self.log_contains("heartbeat is running")) - - self.wait_until( - lambda: self.output_has(lines=1)) - finally: - proc.check_kill_and_wait() - - self.assert_last_status("up") - finally: - server.shutdown() - @parameterized.expand([ (lambda server: "localhost:{}".format(server.server_port), "up"), # This IP is reserved in IPv4