Index: third_party/grpc/test/core/compression/message_compress_test.c |
diff --git a/third_party/grpc/test/core/compression/message_compress_test.c b/third_party/grpc/test/core/compression/message_compress_test.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6d3d16128a8c953b44768d1a7339bca59d8ce7c2 |
--- /dev/null |
+++ b/third_party/grpc/test/core/compression/message_compress_test.c |
@@ -0,0 +1,307 @@ |
+/* |
+ * |
+ * Copyright 2015, Google Inc. |
+ * All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions are |
+ * met: |
+ * |
+ * * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following disclaimer |
+ * in the documentation and/or other materials provided with the |
+ * distribution. |
+ * * Neither the name of Google Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived from |
+ * this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ */ |
+ |
+#include "src/core/compression/message_compress.h" |
+ |
+#include <stdlib.h> |
+#include <string.h> |
+ |
+#include <grpc/grpc.h> |
+#include <grpc/support/log.h> |
+#include <grpc/support/useful.h> |
+ |
+#include "src/core/support/murmur_hash.h" |
+#include "test/core/util/slice_splitter.h" |
+#include "test/core/util/test_config.h" |
+ |
+typedef enum { ONE_A = 0, ONE_KB_A, ONE_MB_A, TEST_VALUE_COUNT } test_value; |
+ |
+typedef enum { |
+ SHOULD_NOT_COMPRESS, |
+ SHOULD_COMPRESS, |
+ MAYBE_COMPRESSES |
+} compressability; |
+ |
+static void assert_passthrough(gpr_slice value, |
+ grpc_compression_algorithm algorithm, |
+ grpc_slice_split_mode uncompressed_split_mode, |
+ grpc_slice_split_mode compressed_split_mode, |
+ compressability compress_result_check) { |
+ gpr_slice_buffer input; |
+ gpr_slice_buffer compressed_raw; |
+ gpr_slice_buffer compressed; |
+ gpr_slice_buffer output; |
+ gpr_slice final; |
+ int was_compressed; |
+ char *algorithm_name; |
+ |
+ GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algorithm_name) != 0); |
+ gpr_log(GPR_INFO, |
+ "assert_passthrough: value_length=%d value_hash=0x%08x " |
+ "algorithm='%s' uncompressed_split='%s' compressed_split='%s'", |
+ GPR_SLICE_LENGTH(value), gpr_murmur_hash3(GPR_SLICE_START_PTR(value), |
+ GPR_SLICE_LENGTH(value), 0), |
+ algorithm_name, grpc_slice_split_mode_name(uncompressed_split_mode), |
+ grpc_slice_split_mode_name(compressed_split_mode)); |
+ |
+ gpr_slice_buffer_init(&input); |
+ gpr_slice_buffer_init(&compressed_raw); |
+ gpr_slice_buffer_init(&compressed); |
+ gpr_slice_buffer_init(&output); |
+ |
+ grpc_split_slices_to_buffer(uncompressed_split_mode, &value, 1, &input); |
+ |
+ was_compressed = grpc_msg_compress(algorithm, &input, &compressed_raw); |
+ GPR_ASSERT(input.count > 0); |
+ |
+ switch (compress_result_check) { |
+ case SHOULD_NOT_COMPRESS: |
+ GPR_ASSERT(was_compressed == 0); |
+ break; |
+ case SHOULD_COMPRESS: |
+ GPR_ASSERT(was_compressed == 1); |
+ break; |
+ case MAYBE_COMPRESSES: |
+ /* no check */ |
+ break; |
+ } |
+ |
+ grpc_split_slice_buffer(compressed_split_mode, &compressed_raw, &compressed); |
+ |
+ GPR_ASSERT(grpc_msg_decompress( |
+ was_compressed ? algorithm : GRPC_COMPRESS_NONE, &compressed, &output)); |
+ |
+ final = grpc_slice_merge(output.slices, output.count); |
+ GPR_ASSERT(0 == gpr_slice_cmp(value, final)); |
+ |
+ gpr_slice_buffer_destroy(&input); |
+ gpr_slice_buffer_destroy(&compressed); |
+ gpr_slice_buffer_destroy(&compressed_raw); |
+ gpr_slice_buffer_destroy(&output); |
+ gpr_slice_unref(final); |
+} |
+ |
+static gpr_slice repeated(char c, size_t length) { |
+ gpr_slice out = gpr_slice_malloc(length); |
+ memset(GPR_SLICE_START_PTR(out), c, length); |
+ return out; |
+} |
+ |
+static compressability get_compressability( |
+ test_value id, grpc_compression_algorithm algorithm) { |
+ if (algorithm == GRPC_COMPRESS_NONE) return SHOULD_NOT_COMPRESS; |
+ switch (id) { |
+ case ONE_A: |
+ return SHOULD_NOT_COMPRESS; |
+ case ONE_KB_A: |
+ case ONE_MB_A: |
+ return SHOULD_COMPRESS; |
+ case TEST_VALUE_COUNT: |
+ abort(); |
+ break; |
+ } |
+ return MAYBE_COMPRESSES; |
+} |
+ |
+static gpr_slice create_test_value(test_value id) { |
+ switch (id) { |
+ case ONE_A: |
+ return gpr_slice_from_copied_string("a"); |
+ case ONE_KB_A: |
+ return repeated('a', 1024); |
+ case ONE_MB_A: |
+ return repeated('a', 1024 * 1024); |
+ case TEST_VALUE_COUNT: |
+ abort(); |
+ break; |
+ } |
+ return gpr_slice_from_copied_string("bad value"); |
+} |
+ |
+static void test_tiny_data_compress(void) { |
+ gpr_slice_buffer input; |
+ gpr_slice_buffer output; |
+ grpc_compression_algorithm i; |
+ |
+ gpr_slice_buffer_init(&input); |
+ gpr_slice_buffer_init(&output); |
+ gpr_slice_buffer_add(&input, create_test_value(ONE_A)); |
+ |
+ for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { |
+ if (i == GRPC_COMPRESS_NONE) continue; |
+ GPR_ASSERT(0 == grpc_msg_compress(i, &input, &output)); |
+ GPR_ASSERT(1 == output.count); |
+ } |
+ |
+ gpr_slice_buffer_destroy(&input); |
+ gpr_slice_buffer_destroy(&output); |
+} |
+ |
+static void test_bad_decompression_data_crc(void) { |
+ gpr_slice_buffer input; |
+ gpr_slice_buffer corrupted; |
+ gpr_slice_buffer output; |
+ size_t idx; |
+ const uint32_t bad = 0xdeadbeef; |
+ |
+ gpr_slice_buffer_init(&input); |
+ gpr_slice_buffer_init(&corrupted); |
+ gpr_slice_buffer_init(&output); |
+ gpr_slice_buffer_add(&input, create_test_value(ONE_MB_A)); |
+ |
+ /* compress it */ |
+ grpc_msg_compress(GRPC_COMPRESS_GZIP, &input, &corrupted); |
+ /* corrupt the output by smashing the CRC */ |
+ GPR_ASSERT(corrupted.count > 1); |
+ GPR_ASSERT(GPR_SLICE_LENGTH(corrupted.slices[1]) > 8); |
+ idx = GPR_SLICE_LENGTH(corrupted.slices[1]) - 8; |
+ memcpy(GPR_SLICE_START_PTR(corrupted.slices[1]) + idx, &bad, 4); |
+ |
+ /* try (and fail) to decompress the corrupted compresed buffer */ |
+ GPR_ASSERT(0 == grpc_msg_decompress(GRPC_COMPRESS_GZIP, &corrupted, &output)); |
+ |
+ gpr_slice_buffer_destroy(&input); |
+ gpr_slice_buffer_destroy(&corrupted); |
+ gpr_slice_buffer_destroy(&output); |
+} |
+ |
+static void test_bad_decompression_data_trailing_garbage(void) { |
+ gpr_slice_buffer input; |
+ gpr_slice_buffer output; |
+ |
+ gpr_slice_buffer_init(&input); |
+ gpr_slice_buffer_init(&output); |
+ /* append 0x99 to the end of an otherwise valid stream */ |
+ gpr_slice_buffer_add( |
+ &input, gpr_slice_from_copied_buffer( |
+ "\x78\xda\x63\x60\x60\x60\x00\x00\x00\x04\x00\x01\x99", 13)); |
+ |
+ /* try (and fail) to decompress the invalid compresed buffer */ |
+ GPR_ASSERT(0 == grpc_msg_decompress(GRPC_COMPRESS_DEFLATE, &input, &output)); |
+ |
+ gpr_slice_buffer_destroy(&input); |
+ gpr_slice_buffer_destroy(&output); |
+} |
+ |
+static void test_bad_decompression_data_stream(void) { |
+ gpr_slice_buffer input; |
+ gpr_slice_buffer output; |
+ |
+ gpr_slice_buffer_init(&input); |
+ gpr_slice_buffer_init(&output); |
+ gpr_slice_buffer_add(&input, |
+ gpr_slice_from_copied_buffer("\x78\xda\xff\xff", 4)); |
+ |
+ /* try (and fail) to decompress the invalid compresed buffer */ |
+ GPR_ASSERT(0 == grpc_msg_decompress(GRPC_COMPRESS_DEFLATE, &input, &output)); |
+ |
+ gpr_slice_buffer_destroy(&input); |
+ gpr_slice_buffer_destroy(&output); |
+} |
+ |
+static void test_bad_compression_algorithm(void) { |
+ gpr_slice_buffer input; |
+ gpr_slice_buffer output; |
+ int was_compressed; |
+ |
+ gpr_slice_buffer_init(&input); |
+ gpr_slice_buffer_init(&output); |
+ gpr_slice_buffer_add(&input, |
+ gpr_slice_from_copied_string("Never gonna give you up")); |
+ was_compressed = |
+ grpc_msg_compress(GRPC_COMPRESS_ALGORITHMS_COUNT, &input, &output); |
+ GPR_ASSERT(0 == was_compressed); |
+ |
+ was_compressed = |
+ grpc_msg_compress(GRPC_COMPRESS_ALGORITHMS_COUNT + 123, &input, &output); |
+ GPR_ASSERT(0 == was_compressed); |
+ |
+ gpr_slice_buffer_destroy(&input); |
+ gpr_slice_buffer_destroy(&output); |
+} |
+ |
+static void test_bad_decompression_algorithm(void) { |
+ gpr_slice_buffer input; |
+ gpr_slice_buffer output; |
+ int was_decompressed; |
+ |
+ gpr_slice_buffer_init(&input); |
+ gpr_slice_buffer_init(&output); |
+ gpr_slice_buffer_add(&input, |
+ gpr_slice_from_copied_string( |
+ "I'm not really compressed but it doesn't matter")); |
+ was_decompressed = |
+ grpc_msg_decompress(GRPC_COMPRESS_ALGORITHMS_COUNT, &input, &output); |
+ GPR_ASSERT(0 == was_decompressed); |
+ |
+ was_decompressed = grpc_msg_decompress(GRPC_COMPRESS_ALGORITHMS_COUNT + 123, |
+ &input, &output); |
+ GPR_ASSERT(0 == was_decompressed); |
+ |
+ gpr_slice_buffer_destroy(&input); |
+ gpr_slice_buffer_destroy(&output); |
+} |
+ |
+int main(int argc, char **argv) { |
+ unsigned i, j, k, m; |
+ grpc_slice_split_mode uncompressed_split_modes[] = { |
+ GRPC_SLICE_SPLIT_IDENTITY, GRPC_SLICE_SPLIT_ONE_BYTE}; |
+ grpc_slice_split_mode compressed_split_modes[] = {GRPC_SLICE_SPLIT_MERGE_ALL, |
+ GRPC_SLICE_SPLIT_IDENTITY, |
+ GRPC_SLICE_SPLIT_ONE_BYTE}; |
+ |
+ grpc_test_init(argc, argv); |
+ grpc_init(); |
+ |
+ for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { |
+ for (j = 0; j < GPR_ARRAY_SIZE(uncompressed_split_modes); j++) { |
+ for (k = 0; k < GPR_ARRAY_SIZE(compressed_split_modes); k++) { |
+ for (m = 0; m < TEST_VALUE_COUNT; m++) { |
+ gpr_slice slice = create_test_value(m); |
+ assert_passthrough(slice, i, j, k, get_compressability(m, i)); |
+ gpr_slice_unref(slice); |
+ } |
+ } |
+ } |
+ } |
+ |
+ test_tiny_data_compress(); |
+ test_bad_decompression_data_crc(); |
+ test_bad_decompression_data_stream(); |
+ test_bad_decompression_data_trailing_garbage(); |
+ test_bad_compression_algorithm(); |
+ test_bad_decompression_algorithm(); |
+ grpc_shutdown(); |
+ |
+ return 0; |
+} |