Revert "Revert "Metadata handling rewrite""

This reverts commit 5e01e2ac977655aa074faf7fde0a74298f5e4c55.
diff --git a/test/core/bad_client/tests/large_metadata.c b/test/core/bad_client/tests/large_metadata.c
index 9c804e7..f672776 100644
--- a/test/core/bad_client/tests/large_metadata.c
+++ b/test/core/bad_client/tests/large_metadata.c
@@ -126,8 +126,8 @@
   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.host, "localhost"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
 
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
@@ -153,16 +153,14 @@
   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.host, "localhost"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
 
   const size_t metadata_value_size = 16 * 1024;
   grpc_metadata meta;
-  meta.key = "key";
-  meta.value = gpr_malloc(metadata_value_size + 1);
-  memset((char *)meta.value, 'a', metadata_value_size);
-  ((char *)meta.value)[metadata_value_size] = 0;
-  meta.value_length = metadata_value_size;
+  meta.key = grpc_slice_from_static_string("key");
+  meta.value = grpc_slice_malloc(metadata_value_size);
+  memset(GRPC_SLICE_START_PTR(meta.value), 'a', metadata_value_size);
 
   grpc_op op;
   memset(&op, 0, sizeof(op));
@@ -176,7 +174,7 @@
   CQ_EXPECT_COMPLETION(cqv, tag(102), 0);  // Operation fails.
   cq_verify(cqv);
 
-  gpr_free((char *)meta.value);
+  grpc_slice_unref(meta.value);
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
   grpc_call_destroy(s);
@@ -190,29 +188,26 @@
   grpc_slice_buffer_trim_end(incoming, 13, &last_frame_buffer);
   GPR_ASSERT(last_frame_buffer.count == 1);
   grpc_slice last_frame = last_frame_buffer.slices[0];
-  // Construct expected frame.
-  grpc_slice expected = grpc_slice_malloc(13);
-  uint8_t *p = GRPC_SLICE_START_PTR(expected);
-  // Length.
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 4;
-  // Frame type (RST_STREAM).
-  *p++ = 3;
-  // Flags.
-  *p++ = 0;
+  const uint8_t *p = GRPC_SLICE_START_PTR(last_frame);
+  // Length = 4
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 4);
+  // Frame type (RST_STREAM)
+  GPR_ASSERT(*p++ == 3);
+  // Flags
+  GPR_ASSERT(*p++ == 0);
   // Stream ID.
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 1;
-  // Payload (error code).
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 0;
-  *p++ = 11;
-  // Compare actual and expected.
-  GPR_ASSERT(grpc_slice_cmp(last_frame, expected) == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 1);
+  // Payload (error code)
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p++ == 0);
+  GPR_ASSERT(*p == 0 || *p == 11);
+
   grpc_slice_buffer_destroy(&last_frame_buffer);
 }
 
diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c
index c08aa40..db31ba6 100644
--- a/test/core/bad_client/tests/simple_request.c
+++ b/test/core/bad_client/tests/simple_request.c
@@ -117,8 +117,8 @@
   CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.host, "localhost"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo/bar"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));
 
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c
index f8a9fe6..9cce77e 100644
--- a/test/core/bad_ssl/bad_ssl_test.c
+++ b/test/core/bad_ssl/bad_ssl_test.c
@@ -57,8 +57,7 @@
 
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array trailing_metadata_recv;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_status_code status;
   grpc_call_error error;
   gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
@@ -80,9 +79,10 @@
   grpc_metadata_array_init(&trailing_metadata_recv);
 
   channel = grpc_secure_channel_create(ssl_creds, target, &args, NULL);
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr:1234");
   c = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                               "/foo", "foo.test.google.fr:1234", deadline,
-                               NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
 
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -95,7 +95,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -117,7 +116,7 @@
   GPR_ASSERT(status != GRPC_STATUS_OK);
 
   grpc_call_destroy(c);
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c
index 080c56f..dd9c544 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -39,6 +39,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/slice/slice_internal.h"
 #include "test/core/util/test_config.h"
 
 static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx,
@@ -120,7 +121,7 @@
   int *channel_data;
   int *call_data;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_mdstr *path = grpc_mdstr_from_string("/service/method");
+  grpc_slice path = grpc_slice_from_static_string("/service/method");
 
   arg.type = GRPC_ARG_INTEGER;
   arg.key = "test_key";
@@ -157,7 +158,7 @@
 
   GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done");
 
-  GRPC_MDSTR_UNREF(&exec_ctx, path);
+  grpc_slice_unref_internal(&exec_ctx, path);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c
index f46982a..d7b1a78 100644
--- a/test/core/client_channel/lb_policies_test.c
+++ b/test/core/client_channel/lb_policies_test.c
@@ -157,8 +157,7 @@
 typedef struct request_data {
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array trailing_metadata_recv;
-  char *details;
-  size_t details_capacity;
+  grpc_slice details;
   grpc_status_code status;
   grpc_call_details *call_details;
 } request_data;
@@ -272,8 +271,6 @@
 
   for (iter_num = 0; iter_num < spec->num_iters; iter_num++) {
     cq_verifier *cqv = cq_verifier_create(f->cq);
-    rdata->details = NULL;
-    rdata->details_capacity = 0;
     was_cancelled = 2;
 
     for (i = 0; i < f->num_servers; i++) {
@@ -294,8 +291,9 @@
     }
     memset(s_valid, 0, f->num_servers * sizeof(int));
 
+    grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
     c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
-                                 "/foo", "foo.test.google.fr",
+                                 grpc_slice_from_static_string("/foo"), &host,
                                  gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
     GPR_ASSERT(c);
     completed_client = 0;
@@ -321,8 +319,6 @@
         &rdata->trailing_metadata_recv;
     op->data.recv_status_on_client.status = &rdata->status;
     op->data.recv_status_on_client.status_details = &rdata->details;
-    op->data.recv_status_on_client.status_details_capacity =
-        &rdata->details_capacity;
     op->flags = 0;
     op->reserved = NULL;
     op++;
@@ -365,7 +361,8 @@
       op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
       op->data.send_status_from_server.trailing_metadata_count = 0;
       op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-      op->data.send_status_from_server.status_details = "xyz";
+      grpc_slice status_details = grpc_slice_from_static_string("xyz");
+      op->data.send_status_from_server.status_details = &status_details;
       op->flags = 0;
       op->reserved = NULL;
       op++;
@@ -384,12 +381,12 @@
       }
       cq_verify(cqv);
 
-      gpr_log(GPR_DEBUG, "status=%d; %s", rdata->status, rdata->details);
       GPR_ASSERT(rdata->status == GRPC_STATUS_UNIMPLEMENTED);
-      GPR_ASSERT(0 == strcmp(rdata->details, "xyz"));
-      GPR_ASSERT(0 == strcmp(rdata->call_details[s_idx].method, "/foo"));
+      GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->details, "xyz"));
       GPR_ASSERT(0 ==
-                 strcmp(rdata->call_details[s_idx].host, "foo.test.google.fr"));
+                 grpc_slice_str_cmp(rdata->call_details[s_idx].method, "/foo"));
+      GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->call_details[s_idx].host,
+                                         "foo.test.google.fr"));
       GPR_ASSERT(was_cancelled == 1);
 
       grpc_call_destroy(f->server_calls[s_idx]);
@@ -422,7 +419,7 @@
     for (i = 0; i < f->num_servers; i++) {
       grpc_call_details_destroy(&rdata->call_details[i]);
     }
-    gpr_free(rdata->details);
+    grpc_slice_unref(rdata->details);
   }
 
   gpr_free(s_valid);
@@ -454,10 +451,12 @@
   op->flags = 0;
   op->reserved = NULL;
 
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
   for (i = 0; i < concurrent_calls; i++) {
-    calls[i] = grpc_channel_create_call(
-        client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
-        "foo.test.google.fr", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+    calls[i] =
+        grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+                                 grpc_slice_from_static_string("/foo"), &host,
+                                 gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
     GPR_ASSERT(calls[i]);
     GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[i], ops,
                                                      (size_t)(op - ops), tag(1),
diff --git a/test/core/client_channel/set_initial_connect_string_test.c b/test/core/client_channel/set_initial_connect_string_test.c
index b78ba98..fc0aca0 100644
--- a/test/core/client_channel/set_initial_connect_string_test.c
+++ b/test/core/client_channel/set_initial_connect_string_test.c
@@ -141,9 +141,11 @@
   } else {
     state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
   }
+  grpc_slice host = grpc_slice_from_static_string("localhost");
   state.call = grpc_channel_create_call(
-      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, "/Service/Method",
-      "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq,
+      grpc_slice_from_static_string("/Service/Method"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   memset(&state.op, 0, sizeof(state.op));
   state.op.op = GRPC_OP_SEND_INITIAL_METADATA;
   state.op.data.send_initial_metadata.count = 0;
@@ -207,8 +209,7 @@
   size_t magic_length = strlen(magic_connect_string);
   GPR_ASSERT(buffer->length >= magic_length);
   for (i = 0, j = 0; i < state.incoming_buffer.count && j < magic_length; i++) {
-    char *dump =
-        grpc_dump_slice(state.incoming_buffer.slices[i], GPR_DUMP_ASCII);
+    char *dump = grpc_slice_to_c_string(state.incoming_buffer.slices[i]);
     cmp_length = GPR_MIN(strlen(dump), magic_length - j);
     GPR_ASSERT(strncmp(dump, magic_connect_string + j, cmp_length) == 0);
     j += cmp_length;
diff --git a/test/core/compression/algorithm_test.c b/test/core/compression/algorithm_test.c
index ff17667..37397ce 100644
--- a/test/core/compression/algorithm_test.c
+++ b/test/core/compression/algorithm_test.c
@@ -40,6 +40,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
@@ -51,32 +52,33 @@
   for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) {
     char *name;
     grpc_compression_algorithm parsed;
-    grpc_mdstr *mdstr;
-    grpc_mdelem *mdelem;
+    grpc_slice mdstr;
+    grpc_mdelem mdelem;
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     GPR_ASSERT(
         grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name));
-    GPR_ASSERT(grpc_compression_algorithm_parse(name, strlen(name), &parsed));
+    GPR_ASSERT(grpc_compression_algorithm_parse(
+        grpc_slice_from_static_string(name), &parsed));
     GPR_ASSERT((int)parsed == i);
-    mdstr = grpc_mdstr_from_string(name);
-    GPR_ASSERT(mdstr == grpc_compression_algorithm_mdstr(parsed));
-    GPR_ASSERT(parsed == grpc_compression_algorithm_from_mdstr(mdstr));
+    mdstr = grpc_slice_from_copied_string(name);
+    GPR_ASSERT(grpc_slice_eq(mdstr, grpc_compression_algorithm_slice(parsed)));
+    GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr));
     mdelem = grpc_compression_encoding_mdelem(parsed);
-    GPR_ASSERT(mdelem->value == mdstr);
-    GPR_ASSERT(mdelem->key == GRPC_MDSTR_GRPC_ENCODING);
-    GRPC_MDSTR_UNREF(&exec_ctx, mdstr);
+    GPR_ASSERT(grpc_slice_eq(GRPC_MDVALUE(mdelem), mdstr));
+    GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_GRPC_ENCODING));
+    grpc_slice_unref_internal(&exec_ctx, mdstr);
     GRPC_MDELEM_UNREF(&exec_ctx, mdelem);
     grpc_exec_ctx_finish(&exec_ctx);
   }
 
   /* test failure */
-  GPR_ASSERT(NULL ==
-             grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT));
+  GPR_ASSERT(GRPC_MDISNULL(
+      grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT)));
 }
 
 static void test_algorithm_failure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_mdstr *mdstr;
+  grpc_slice mdstr;
 
   gpr_log(GPR_DEBUG, "test_algorithm_failure");
 
@@ -84,14 +86,16 @@
                                              NULL) == 0);
   GPR_ASSERT(grpc_compression_algorithm_name(GRPC_COMPRESS_ALGORITHMS_COUNT + 1,
                                              NULL) == 0);
-  mdstr = grpc_mdstr_from_string("this-is-an-invalid-algorithm");
-  GPR_ASSERT(grpc_compression_algorithm_from_mdstr(mdstr) ==
+  mdstr = grpc_slice_from_static_string("this-is-an-invalid-algorithm");
+  GPR_ASSERT(grpc_compression_algorithm_from_slice(mdstr) ==
              GRPC_COMPRESS_ALGORITHMS_COUNT);
-  GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT) ==
-             NULL);
-  GPR_ASSERT(grpc_compression_algorithm_mdstr(GRPC_COMPRESS_ALGORITHMS_COUNT +
-                                              1) == NULL);
-  GRPC_MDSTR_UNREF(&exec_ctx, mdstr);
+  GPR_ASSERT(grpc_slice_eq(
+      grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT),
+      grpc_empty_slice()));
+  GPR_ASSERT(grpc_slice_eq(
+      grpc_compression_algorithm_slice(GRPC_COMPRESS_ALGORITHMS_COUNT + 1),
+      grpc_empty_slice()));
+  grpc_slice_unref_internal(&exec_ctx, mdstr);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
diff --git a/test/core/compression/compression_test.c b/test/core/compression/compression_test.c
index 4c43746..7b2e56d 100644
--- a/test/core/compression/compression_test.c
+++ b/test/core/compression/compression_test.c
@@ -54,7 +54,7 @@
     const char *valid_name = valid_names[i];
     grpc_compression_algorithm algorithm;
     const int success = grpc_compression_algorithm_parse(
-        valid_name, strlen(valid_name), &algorithm);
+        grpc_slice_from_static_string(valid_name), &algorithm);
     GPR_ASSERT(success != 0);
     GPR_ASSERT(algorithm == valid_algorithms[i]);
   }
@@ -64,7 +64,7 @@
     grpc_compression_algorithm algorithm;
     int success;
     success = grpc_compression_algorithm_parse(
-        invalid_name, strlen(invalid_name), &algorithm);
+        grpc_slice_from_static_string(invalid_name), &algorithm);
     GPR_ASSERT(success == 0);
     /* the value of "algorithm" is undefined upon failure */
   }
diff --git a/test/core/compression/message_compress_test.c b/test/core/compression/message_compress_test.c
index 2432ca7..246a2b3 100644
--- a/test/core/compression/message_compress_test.c
+++ b/test/core/compression/message_compress_test.c
@@ -114,7 +114,7 @@
   }
 
   final = grpc_slice_merge(output.slices, output.count);
-  GPR_ASSERT(0 == grpc_slice_cmp(value, final));
+  GPR_ASSERT(grpc_slice_eq(value, final));
 
   grpc_slice_buffer_destroy(&input);
   grpc_slice_buffer_destroy(&compressed);
diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c
index a052016..12db8a1 100644
--- a/test/core/end2end/bad_server_response_test.c
+++ b/test/core/end2end/bad_server_response_test.c
@@ -172,16 +172,17 @@
   grpc_status_code status;
   grpc_call_error error;
   cq_verifier *cqv;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   state.cq = grpc_completion_queue_create(NULL);
   cqv = cq_verifier_create(state.cq);
   gpr_join_host_port(&state.target, "127.0.0.1", target_port);
   state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
   state.call = grpc_channel_create_call(
-      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, "/Service/Method",
-      "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq,
+      grpc_slice_from_static_string("/Service/Method"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 
   grpc_metadata_array_init(&initial_metadata_recv);
   grpc_metadata_array_init(&trailing_metadata_recv);
@@ -206,7 +207,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -218,13 +218,13 @@
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  gpr_log(GPR_DEBUG, "Rpc status: %d, details: %s", status, details);
   GPR_ASSERT(status == expected_status);
-  GPR_ASSERT(NULL != strstr(details, expected_detail));
+  GPR_ASSERT(-1 != grpc_slice_slice(details, grpc_slice_from_static_string(
+                                                 expected_detail)));
 
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
   cq_verifier_destroy(cqv);
 }
 
diff --git a/test/core/end2end/connection_refused_test.c b/test/core/end2end/connection_refused_test.c
index 4430804..81a6b87 100644
--- a/test/core/end2end/connection_refused_test.c
+++ b/test/core/end2end/connection_refused_test.c
@@ -40,6 +40,7 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/service_config.h"
 
@@ -59,8 +60,7 @@
   grpc_op *op;
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   gpr_log(GPR_INFO, "TEST: wait_for_ready=%d use_service_config=%d",
           wait_for_ready, use_service_config);
@@ -97,9 +97,10 @@
   gpr_join_host_port(&addr, "127.0.0.1", port);
   gpr_log(GPR_INFO, "server: %s", addr);
   chan = grpc_insecure_channel_create(addr, args, NULL);
-  call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/service/method", "nonexistant", deadline,
-                                  NULL);
+  grpc_slice host = grpc_slice_from_static_string("nonexistant");
+  call = grpc_channel_create_call(
+      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/service/method"), &host, deadline, NULL);
 
   gpr_free(addr);
 
@@ -116,7 +117,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -142,7 +142,7 @@
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
   {
diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c
index 5737397..bc2d588 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -92,8 +92,8 @@
                         const char *value) {
   size_t i;
   for (i = 0; i < count; i++) {
-    if (0 == strcmp(key, md[i].key) && strlen(value) == md[i].value_length &&
-        0 == memcmp(md[i].value, value, md[i].value_length)) {
+    if (0 == grpc_slice_str_cmp(md[i].key, key) &&
+        0 == grpc_slice_str_cmp(md[i].value, value)) {
       return 1;
     }
   }
@@ -105,6 +105,22 @@
   return has_metadata(array->metadata, array->count, key, value);
 }
 
+static int has_metadata_slices(const grpc_metadata *md, size_t count,
+                               grpc_slice key, grpc_slice value) {
+  size_t i;
+  for (i = 0; i < count; i++) {
+    if (grpc_slice_eq(md[i].key, key) && grpc_slice_eq(md[i].value, value)) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key,
+                             grpc_slice value) {
+  return has_metadata_slices(array->metadata, array->count, key, value);
+}
+
 static grpc_slice merge_slices(grpc_slice *slices, size_t nslices) {
   size_t i;
   size_t len = 0;
diff --git a/test/core/end2end/cq_verifier.h b/test/core/end2end/cq_verifier.h
index b754de9..035aa27 100644
--- a/test/core/end2end/cq_verifier.h
+++ b/test/core/end2end/cq_verifier.h
@@ -71,5 +71,7 @@
 int byte_buffer_eq_string(grpc_byte_buffer *byte_buffer, const char *string);
 int contains_metadata(grpc_metadata_array *array, const char *key,
                       const char *value);
+int contains_metadata_slices(grpc_metadata_array *array, grpc_slice key,
+                             grpc_slice value);
 
 #endif /* GRPC_TEST_CORE_END2END_CQ_VERIFIER_H */
diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c
index 11e8604..9cd0707 100644
--- a/test/core/end2end/dualstack_socket_test.c
+++ b/test/core/end2end/dualstack_socket_test.c
@@ -88,8 +88,7 @@
   grpc_metadata_array request_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   grpc_call_details call_details;
   char *peer;
@@ -135,7 +134,7 @@
     grpc_slice_split(uri_slice, ",", &uri_parts);
     hosts_with_port = gpr_malloc(sizeof(char *) * uri_parts.count);
     for (i = 0; i < uri_parts.count; i++) {
-      char *uri_part_str = grpc_dump_slice(uri_parts.slices[i], GPR_DUMP_ASCII);
+      char *uri_part_str = grpc_slice_to_c_string(uri_parts.slices[i]);
       gpr_asprintf(&hosts_with_port[i], "%s:%d", uri_part_str, port);
       gpr_free(uri_part_str);
     }
@@ -168,8 +167,10 @@
   }
 
   /* Send a trivial request. */
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
   c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                               "/foo", "foo.test.google.fr", deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   memset(ops, 0, sizeof(ops));
@@ -192,7 +193,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -216,7 +216,8 @@
     op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
     op->data.send_status_from_server.trailing_metadata_count = 0;
     op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-    op->data.send_status_from_server.status_details = "xyz";
+    grpc_slice status_details = grpc_slice_from_static_string("xyz");
+    op->data.send_status_from_server.status_details = &status_details;
     op->flags = 0;
     op++;
     op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
@@ -235,9 +236,10 @@
     gpr_free(peer);
 
     GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-    GPR_ASSERT(0 == strcmp(details, "xyz"));
-    GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
-    GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
+    GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+    GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+    GPR_ASSERT(0 ==
+               grpc_slice_str_cmp(call_details.host, "foo.test.google.fr"));
     GPR_ASSERT(was_cancelled == 1);
 
     grpc_call_destroy(s);
@@ -271,7 +273,7 @@
   grpc_metadata_array_destroy(&request_metadata_recv);
 
   grpc_call_details_destroy(&call_details);
-  gpr_free(details);
+  grpc_slice_unref(details);
   if (picked_port) {
     grpc_recycle_unused_port(port);
   }
diff --git a/test/core/end2end/end2end_test_utils.c b/test/core/end2end/end2end_test_utils.c
index 46fb4ec..8783d84 100644
--- a/test/core/end2end/end2end_test_utils.c
+++ b/test/core/end2end/end2end_test_utils.c
@@ -39,13 +39,27 @@
 
 const char *get_host_override_string(const char *str,
                                      grpc_end2end_test_config config) {
-  return (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER ? str
-                                                                       : NULL);
+  if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) {
+    return str;
+  } else {
+    return NULL;
+  }
 }
 
-void validate_host_override_string(const char *pattern, const char *str,
+const grpc_slice *get_host_override_slice(const char *str,
+                                          grpc_end2end_test_config config) {
+  const char *r = get_host_override_string(str, config);
+  if (r != NULL) {
+    static grpc_slice ret;
+    ret = grpc_slice_from_static_string(r);
+    return &ret;
+  }
+  return NULL;
+}
+
+void validate_host_override_string(const char *pattern, grpc_slice str,
                                    grpc_end2end_test_config config) {
   if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) {
-    GPR_ASSERT(0 == strcmp(str, pattern));
+    GPR_ASSERT(0 == grpc_slice_str_cmp(str, pattern));
   }
 }
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index f25e90b..cb0afd9 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -72,8 +72,12 @@
 
 const char *get_host_override_string(const char *str,
                                      grpc_end2end_test_config config);
+/* Returns a pointer to a statically allocated slice: future invocations
+   overwrite past invocations, not threadsafe, etc... */
+const grpc_slice *get_host_override_slice(const char *str,
+                                          grpc_end2end_test_config config);
 
-void validate_host_override_string(const char *pattern, const char *str,
+void validate_host_override_string(const char *pattern, grpc_slice str,
                                    grpc_end2end_test_config config);
 
 #endif /* GRPC_TEST_CORE_END2END_END2END_TESTS_H */
diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c
index 966642f..8e711c6 100644
--- a/test/core/end2end/fake_resolver.c
+++ b/test/core/end2end/fake_resolver.c
@@ -165,7 +165,7 @@
   bool errors_found = false;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_uri ith_uri = *args->uri;
-    char* part_str = grpc_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
+    char* part_str = grpc_slice_to_c_string(path_parts.slices[i]);
     ith_uri.path = part_str;
     if (!parse_ipv4(&ith_uri, &addresses->addresses[i].address)) {
       errors_found = true;
diff --git a/test/core/end2end/fixtures/h2_oauth2.c b/test/core/end2end/fixtures/h2_oauth2.c
index 83f759c..3351652 100644
--- a/test/core/end2end/fixtures/h2_oauth2.c
+++ b/test/core/end2end/fixtures/h2_oauth2.c
@@ -59,8 +59,8 @@
                                           const char *value) {
   size_t i;
   for (i = 0; i < md_count; i++) {
-    if (strcmp(key, md[i].key) == 0 && strlen(value) == md[i].value_length &&
-        memcmp(md[i].value, value, md[i].value_length) == 0) {
+    if (grpc_slice_str_cmp(md[i].key, key) == 0 &&
+        grpc_slice_str_cmp(md[i].value, value) == 0) {
       return &md[i];
     }
   }
@@ -74,7 +74,7 @@
                                    grpc_process_auth_metadata_done_cb cb,
                                    void *user_data) {
   const grpc_metadata *oauth2 =
-      find_metadata(md, md_count, "Authorization", oauth2_md);
+      find_metadata(md, md_count, "authorization", oauth2_md);
   test_processor_state *s;
 
   GPR_ASSERT(state != NULL);
@@ -93,7 +93,7 @@
                                    grpc_process_auth_metadata_done_cb cb,
                                    void *user_data) {
   const grpc_metadata *oauth2 =
-      find_metadata(md, md_count, "Authorization", oauth2_md);
+      find_metadata(md, md_count, "authorization", oauth2_md);
   test_processor_state *s;
   GPR_ASSERT(state != NULL);
   s = (test_processor_state *)state;
@@ -154,7 +154,7 @@
   grpc_channel_credentials *ssl_creds =
       grpc_ssl_credentials_create(test_root_cert, NULL, NULL);
   grpc_call_credentials *oauth2_creds =
-      grpc_md_only_test_credentials_create("Authorization", oauth2_md, 1);
+      grpc_md_only_test_credentials_create("authorization", oauth2_md, 1);
   grpc_channel_credentials *ssl_oauth2_creds =
       grpc_composite_channel_credentials_create(ssl_creds, oauth2_creds, NULL);
   grpc_arg ssl_name_override = {GRPC_ARG_STRING,
diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/fixtures/h2_ssl_cert.c
index ae49cc8..844e933 100644
--- a/test/core/end2end/fixtures/h2_ssl_cert.c
+++ b/test/core/end2end/fixtures/h2_ssl_cert.c
@@ -321,9 +321,10 @@
   grpc_op *op;
   grpc_call_error error;
 
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr:1234");
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "foo.test.google.fr:1234", deadline,
-                               NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   memset(ops, 0, sizeof(ops));
diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy.c
index b62082c..dac9baf 100644
--- a/test/core/end2end/fixtures/http_proxy.c
+++ b/test/core/end2end/fixtures/http_proxy.c
@@ -132,7 +132,7 @@
                                     const char* prefix, grpc_error* error) {
   const char* msg = grpc_error_string(error);
   gpr_log(GPR_INFO, "%s: %s", prefix, msg);
-  grpc_error_free_string(msg);
+
   grpc_endpoint_shutdown(exec_ctx, conn->client_endpoint);
   if (conn->server_endpoint != NULL)
     grpc_endpoint_shutdown(exec_ctx, conn->server_endpoint);
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index beed80d..30bb9ff 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -80,8 +80,7 @@
 
   grpc_metadata_array p2s_trailing_metadata;
   grpc_status_code p2s_status;
-  char *p2s_status_details;
-  size_t p2s_status_details_capacity;
+  grpc_slice p2s_status_details;
 
   int c2p_server_cancelled;
 } proxy_call;
@@ -112,6 +111,7 @@
   grpc_server_register_completion_queue(proxy->server, proxy->cq, NULL);
   grpc_server_start(proxy->server);
 
+  grpc_call_details_init(&proxy->new_call_details);
   gpr_thd_options_set_joinable(&opt);
   GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt));
 
@@ -153,7 +153,7 @@
     grpc_metadata_array_destroy(&pc->c2p_initial_metadata);
     grpc_metadata_array_destroy(&pc->p2s_initial_metadata);
     grpc_metadata_array_destroy(&pc->p2s_trailing_metadata);
-    gpr_free(pc->p2s_status_details);
+    grpc_slice_unref(pc->p2s_status_details);
     gpr_free(pc);
   }
 }
@@ -309,7 +309,7 @@
     op.data.send_status_from_server.trailing_metadata =
         pc->p2s_trailing_metadata.metadata;
     op.data.send_status_from_server.status = pc->p2s_status;
-    op.data.send_status_from_server.status_details = pc->p2s_status_details;
+    op.data.send_status_from_server.status_details = &pc->p2s_status_details;
     refpc(pc, "on_c2p_sent_status");
     err = grpc_call_start_batch(pc->c2p, &op, 1,
                                 new_closure(on_c2p_sent_status, pc), NULL);
@@ -339,7 +339,7 @@
     pc->c2p = proxy->new_call;
     pc->p2s = grpc_channel_create_call(
         proxy->client, pc->c2p, GRPC_PROPAGATE_DEFAULTS, proxy->cq,
-        proxy->new_call_details.method, proxy->new_call_details.host,
+        proxy->new_call_details.method, &proxy->new_call_details.host,
         proxy->new_call_details.deadline, NULL);
     gpr_ref_init(&pc->refs, 1);
 
@@ -384,8 +384,6 @@
         &pc->p2s_trailing_metadata;
     op.data.recv_status_on_client.status = &pc->p2s_status;
     op.data.recv_status_on_client.status_details = &pc->p2s_status_details;
-    op.data.recv_status_on_client.status_details_capacity =
-        &pc->p2s_status_details_capacity;
     refpc(pc, "on_p2s_status");
     err = grpc_call_start_batch(pc->p2s, &op, 1, new_closure(on_p2s_status, pc),
                                 NULL);
@@ -401,6 +399,9 @@
 
     request_call(proxy);
 
+    grpc_call_details_destroy(&proxy->new_call_details);
+    grpc_call_details_init(&proxy->new_call_details);
+
     unrefpc(pc, "init");
   } else {
     GPR_ASSERT(proxy->new_call == NULL);
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index 200a518..30d814b 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -44,6 +44,7 @@
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/tcp_client.h"
 #include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/transport/metadata.h"
 #include "test/core/end2end/data/ssl_test_data.h"
@@ -90,7 +91,7 @@
 
 static void end(input_stream *inp) { inp->cur = inp->end; }
 
-static char *read_string(input_stream *inp) {
+static char *read_string(input_stream *inp, bool *special) {
   char *str = NULL;
   size_t cap = 0;
   size_t sz = 0;
@@ -102,18 +103,56 @@
     }
     c = (char)next_byte(inp);
     str[sz++] = c;
-  } while (c != 0);
+  } while (c != 0 && c != 1);
+  if (special != NULL) {
+    *special = (c == 1);
+  }
+  if (c == 1) {
+    str[sz - 1] = 0;
+  }
   return str;
 }
 
-static void read_buffer(input_stream *inp, char **buffer, size_t *length) {
+static void read_buffer(input_stream *inp, char **buffer, size_t *length,
+                        bool *special) {
   *length = next_byte(inp);
+  if (*length == 255) {
+    if (special != NULL) *special = true;
+    *length = next_byte(inp);
+  } else {
+    if (special != NULL) *special = false;
+  }
   *buffer = gpr_malloc(*length);
   for (size_t i = 0; i < *length; i++) {
     (*buffer)[i] = (char)next_byte(inp);
   }
 }
 
+static grpc_slice maybe_intern(grpc_slice s, bool intern) {
+  grpc_slice r = intern ? grpc_slice_intern(s) : grpc_slice_ref(s);
+  grpc_slice_unref(s);
+  return r;
+}
+
+static grpc_slice read_string_like_slice(input_stream *inp) {
+  bool special;
+  char *s = read_string(inp, &special);
+  grpc_slice r = maybe_intern(grpc_slice_from_copied_string(s), special);
+  gpr_free(s);
+  return r;
+}
+
+static grpc_slice read_buffer_like_slice(input_stream *inp) {
+  char *buffer;
+  size_t length;
+  bool special;
+  read_buffer(inp, &buffer, &length, &special);
+  grpc_slice r =
+      maybe_intern(grpc_slice_from_copied_buffer(buffer, length), special);
+  gpr_free(buffer);
+  return r;
+}
+
 static uint32_t read_uint22(input_stream *inp) {
   uint8_t b = next_byte(inp);
   uint32_t x = b & 0x7f;
@@ -170,12 +209,12 @@
     switch (next_byte(inp)) {
       case 1:
         args[i].type = GRPC_ARG_STRING;
-        args[i].key = read_string(inp);
-        args[i].value.string = read_string(inp);
+        args[i].key = read_string(inp, NULL);
+        args[i].value.string = read_string(inp, NULL);
         break;
       case 2:
         args[i].type = GRPC_ARG_INTEGER;
-        args[i].key = read_string(inp);
+        args[i].key = read_string(inp, NULL);
         args[i].value.integer = read_int(inp);
         break;
       case 3:
@@ -217,7 +256,7 @@
                                       size_t num_builtins) {
   uint8_t b = next_byte(inp);
   if (b == 0) return NULL;
-  if (b == 1) return ctx->release[ctx->num_release++] = read_string(inp);
+  if (b == 1) return ctx->release[ctx->num_release++] = read_string(inp, NULL);
   if (b >= num_builtins + 1) {
     end(inp);
     return NULL;
@@ -508,8 +547,7 @@
   grpc_status_code status;
   grpc_metadata_array recv_initial_metadata;
   grpc_metadata_array recv_trailing_metadata;
-  char *recv_status_details;
-  size_t recv_status_details_capacity;
+  grpc_slice recv_status_details;
   int cancelled;
   int pending_ops;
   grpc_call_details call_details;
@@ -523,6 +561,11 @@
   size_t cap_to_free;
   void **to_free;
 
+  // array of slices to unref
+  size_t num_slices_to_unref;
+  size_t cap_slices_to_unref;
+  grpc_slice *slices_to_unref;
+
   struct call_state *next;
   struct call_state *prev;
 } call_state;
@@ -558,12 +601,15 @@
   call->next->prev = call->prev;
   grpc_metadata_array_destroy(&call->recv_initial_metadata);
   grpc_metadata_array_destroy(&call->recv_trailing_metadata);
-  gpr_free(call->recv_status_details);
+  grpc_slice_unref(call->recv_status_details);
   grpc_call_details_destroy(&call->call_details);
 
   for (size_t i = 0; i < call->num_to_free; i++) {
     gpr_free(call->to_free[i]);
   }
+  for (size_t i = 0; i < call->num_slices_to_unref; i++) {
+    grpc_slice_unref(call->slices_to_unref[i]);
+  }
   gpr_free(call->to_free);
 
   gpr_free(call);
@@ -580,6 +626,17 @@
   call->to_free[call->num_to_free++] = p;
 }
 
+static grpc_slice *add_to_slice_unref(call_state *call, grpc_slice s) {
+  if (call->num_slices_to_unref == call->cap_slices_to_unref) {
+    call->cap_slices_to_unref = GPR_MAX(8, 2 * call->cap_slices_to_unref);
+    call->slices_to_unref =
+        gpr_realloc(call->slices_to_unref,
+                    sizeof(*call->slices_to_unref) * call->cap_slices_to_unref);
+  }
+  call->slices_to_unref[call->num_to_free++] = s;
+  return &call->slices_to_unref[call->num_to_free - 1];
+}
+
 static void read_metadata(input_stream *inp, size_t *count,
                           grpc_metadata **metadata, call_state *cs) {
   *count = next_byte(inp);
@@ -587,12 +644,11 @@
     *metadata = gpr_malloc(*count * sizeof(**metadata));
     memset(*metadata, 0, *count * sizeof(**metadata));
     for (size_t i = 0; i < *count; i++) {
-      (*metadata)[i].key = read_string(inp);
-      read_buffer(inp, (char **)&(*metadata)[i].value,
-                  &(*metadata)[i].value_length);
+      (*metadata)[i].key = read_string_like_slice(inp);
+      (*metadata)[i].value = read_buffer_like_slice(inp);
       (*metadata)[i].flags = read_uint32(inp);
-      add_to_free(cs, (void *)(*metadata)[i].key);
-      add_to_free(cs, (void *)(*metadata)[i].value);
+      add_to_slice_unref(cs, (*metadata)[i].key);
+      add_to_slice_unref(cs, (*metadata)[i].value);
     }
   } else {
     *metadata = gpr_malloc(1);
@@ -656,7 +712,7 @@
 }
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   if (squelch) gpr_set_log_function(dont_log);
   input_stream inp = {data, data + size};
   grpc_resolve_address = my_resolve_address;
@@ -742,7 +798,7 @@
       // create an insecure channel
       case 2: {
         if (g_channel == NULL) {
-          char *target = read_string(&inp);
+          char *target = read_string(&inp, NULL);
           char *target_uri;
           gpr_asprintf(&target_uri, "dns:%s", target);
           grpc_channel_args *args = read_args(&inp);
@@ -871,8 +927,8 @@
           parent_call = g_active_call->call;
         }
         uint32_t propagation_mask = read_uint32(&inp);
-        char *method = read_string(&inp);
-        char *host = read_string(&inp);
+        grpc_slice method = read_string_like_slice(&inp);
+        grpc_slice host = read_string_like_slice(&inp);
         gpr_timespec deadline =
             gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                          gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
@@ -881,12 +937,12 @@
           call_state *cs = new_call(g_active_call, CLIENT);
           cs->call =
               grpc_channel_create_call(g_channel, parent_call, propagation_mask,
-                                       cq, method, host, deadline, NULL);
+                                       cq, method, &host, deadline, NULL);
         } else {
           end(&inp);
         }
-        gpr_free(method);
-        gpr_free(host);
+        grpc_slice_unref(method);
+        grpc_slice_unref(host);
         break;
       }
       // switch the 'current' call
@@ -951,7 +1007,8 @@
                   g_active_call);
               op->data.send_status_from_server.status = next_byte(&inp);
               op->data.send_status_from_server.status_details =
-                  read_string(&inp);
+                  add_to_slice_unref(g_active_call,
+                                     read_buffer_like_slice(&inp));
               break;
             case GRPC_OP_RECV_INITIAL_METADATA:
               op->op = GRPC_OP_RECV_INITIAL_METADATA;
@@ -971,8 +1028,6 @@
                   &g_active_call->recv_trailing_metadata;
               op->data.recv_status_on_client.status_details =
                   &g_active_call->recv_status_details;
-              op->data.recv_status_on_client.status_details_capacity =
-                  &g_active_call->recv_status_details_capacity;
               break;
             case GRPC_OP_RECV_CLOSE_ON_SERVER:
               op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
@@ -1060,14 +1115,14 @@
       }
       // enable a tracer
       case 17: {
-        char *tracer = read_string(&inp);
+        char *tracer = read_string(&inp, NULL);
         grpc_tracer_set_enabled(tracer, 1);
         gpr_free(tracer);
         break;
       }
       // disable a tracer
       case 18: {
-        char *tracer = read_string(&inp);
+        char *tracer = read_string(&inp, NULL);
         grpc_tracer_set_enabled(tracer, 0);
         gpr_free(tracer);
         break;
@@ -1109,7 +1164,7 @@
       // create a secure channel
       case 22: {
         if (g_channel == NULL) {
-          char *target = read_string(&inp);
+          char *target = read_string(&inp, NULL);
           char *target_uri;
           gpr_asprintf(&target_uri, "dns:%s", target);
           grpc_channel_args *args = read_args(&inp);
diff --git a/test/core/end2end/fuzzers/client_fuzzer.c b/test/core/end2end/fuzzers/client_fuzzer.c
index 26b5208..1fdc863 100644
--- a/test/core/end2end/fuzzers/client_fuzzer.c
+++ b/test/core/end2end/fuzzers/client_fuzzer.c
@@ -37,6 +37,7 @@
 #include <grpc/support/alloc.h>
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/channel.h"
 #include "test/core/util/memory_counters.h"
 #include "test/core/util/mock_endpoint.h"
@@ -51,7 +52,7 @@
 static void dont_log(gpr_log_func_args *args) {}
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   struct grpc_memory_counters counters;
   if (squelch) gpr_set_log_function(dont_log);
   if (leak_check) grpc_memory_counters_init();
@@ -71,9 +72,10 @@
 
   grpc_channel *channel = grpc_channel_create(
       &exec_ctx, "test-target", NULL, GRPC_CLIENT_DIRECT_CHANNEL, transport);
-  grpc_call *call =
-      grpc_channel_create_call(channel, NULL, 0, cq, "/foo", "localhost",
-                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
+  grpc_call *call = grpc_channel_create_call(
+      channel, NULL, 0, cq, grpc_slice_from_static_string("/foo"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -81,8 +83,7 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_metadata_array_init(&trailing_metadata_recv);
   grpc_status_code status;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details = grpc_empty_slice();
 
   grpc_op ops[6];
   memset(ops, 0, sizeof(ops));
@@ -110,7 +111,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -155,7 +155,7 @@
   grpc_completion_queue_destroy(cq);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_channel_destroy(channel);
   if (response_payload_recv != NULL) {
     grpc_byte_buffer_destroy(response_payload_recv);
diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary
index 12db0ff..81a2419 100644
--- a/test/core/end2end/fuzzers/hpack.dictionary
+++ b/test/core/end2end/fuzzers/hpack.dictionary
@@ -1,24 +1,62 @@
 # hpack fuzzing dictionary
+"\x05:path"
+"\x07:method"
+"\x07:status"
+"\x0A:authority"
+"\x07:scheme"
+"\x02te"
+"\x0Cgrpc-message"
+"\x0Bgrpc-status"
+"\x10grpc-payload-bin"
+"\x0Dgrpc-encoding"
+"\x14grpc-accept-encoding"
+"\x0Ccontent-type"
+"\x1Egrpc-internal-encoding-request"
+"\x0Auser-agent"
+"\x04host"
+"\x08lb-token"
+"\x0Blb-cost-bin"
+"\x0Cgrpc-timeout"
+"\x10grpc-tracing-bin"
+"\x0Egrpc-stats-bin"
+"\x00"
+"\x13grpc.wait_for_ready"
+"\x0Cgrpc.timeout"
+"\x1Egrpc.max_request_message_bytes"
+"\x1Fgrpc.max_response_message_bytes"
+"$/grpc.lb.v1.LoadBalancer/BalanceLoad"
 "\x010"
 "\x011"
 "\x012"
+"\x08identity"
+"\x04gzip"
+"\x07deflate"
+"\x08trailers"
+"\x10application/grpc"
+"\x04POST"
 "\x03200"
+"\x03404"
+"\x04http"
+"\x05https"
+"\x04grpc"
+"\x03GET"
+"\x03PUT"
+"\x01/"
+"\x0B/index.html"
 "\x03204"
 "\x03206"
 "\x03304"
 "\x03400"
-"\x03404"
 "\x03500"
-"\x06accept"
 "\x0Eaccept-charset"
 "\x0Faccept-encoding"
+"\x0Dgzip, deflate"
 "\x0Faccept-language"
 "\x0Daccept-ranges"
+"\x06accept"
 "\x1Baccess-control-allow-origin"
 "\x03age"
 "\x05allow"
-"\x10application/grpc"
-"\x0A:authority"
 "\x0Dauthorization"
 "\x0Dcache-control"
 "\x13content-disposition"
@@ -27,81 +65,71 @@
 "\x0Econtent-length"
 "\x10content-location"
 "\x0Dcontent-range"
-"\x0Ccontent-type"
 "\x06cookie"
 "\x04date"
-"\x07deflate"
-"\x0Cdeflate,gzip"
-"\x00"
 "\x04etag"
 "\x06expect"
 "\x07expires"
 "\x04from"
-"\x03GET"
-"\x04grpc"
-"\x14grpc-accept-encoding"
-"\x0Dgrpc-encoding"
-"\x1Egrpc-internal-encoding-request"
-"\x0Cgrpc-message"
-"\x10grpc-payload-bin"
-"\x0Egrpc-stats-bin"
-"\x0Bgrpc-status"
-"\x0Cgrpc-timeout"
-"\x10grpc-tracing-bin"
-"\x04gzip"
-"\x0Dgzip, deflate"
-"\x04host"
-"\x04http"
-"\x05https"
-"\x08identity"
-"\x10identity,deflate"
-"\x15identity,deflate,gzip"
-"\x0Didentity,gzip"
 "\x08if-match"
 "\x11if-modified-since"
 "\x0Dif-none-match"
 "\x08if-range"
 "\x13if-unmodified-since"
 "\x0Dlast-modified"
-"\x0Blb-cost-bin"
-"\x08lb-token"
 "\x04link"
 "\x08location"
 "\x0Cmax-forwards"
-"\x07:method"
-"\x05:path"
-"\x04POST"
 "\x12proxy-authenticate"
 "\x13proxy-authorization"
-"\x03PUT"
 "\x05range"
 "\x07referer"
 "\x07refresh"
 "\x0Bretry-after"
-"\x07:scheme"
 "\x06server"
 "\x0Aset-cookie"
-"\x01/"
-"\x0B/index.html"
-"\x07:status"
 "\x19strict-transport-security"
-"\x02te"
-"\x08trailers"
 "\x11transfer-encoding"
-"\x0Auser-agent"
 "\x04vary"
 "\x03via"
 "\x10www-authenticate"
+"\x10identity,deflate"
+"\x0Didentity,gzip"
+"\x0Cdeflate,gzip"
+"\x15identity,deflate,gzip"
+"\x00\x0Bgrpc-status\x010"
+"\x00\x0Bgrpc-status\x011"
+"\x00\x0Bgrpc-status\x012"
+"\x00\x0Dgrpc-encoding\x08identity"
+"\x00\x0Dgrpc-encoding\x04gzip"
+"\x00\x0Dgrpc-encoding\x07deflate"
+"\x00\x02te\x08trailers"
+"\x00\x0Ccontent-type\x10application/grpc"
+"\x00\x07:method\x04POST"
+"\x00\x07:status\x03200"
+"\x00\x07:status\x03404"
+"\x00\x07:scheme\x04http"
+"\x00\x07:scheme\x05https"
+"\x00\x07:scheme\x04grpc"
+"\x00\x0A:authority\x00"
+"\x00\x07:method\x03GET"
+"\x00\x07:method\x03PUT"
+"\x00\x05:path\x01/"
+"\x00\x05:path\x0B/index.html"
+"\x00\x07:status\x03204"
+"\x00\x07:status\x03206"
+"\x00\x07:status\x03304"
+"\x00\x07:status\x03400"
+"\x00\x07:status\x03500"
 "\x00\x0Eaccept-charset\x00"
-"\x00\x06accept\x00"
 "\x00\x0Faccept-encoding\x00"
 "\x00\x0Faccept-encoding\x0Dgzip, deflate"
 "\x00\x0Faccept-language\x00"
 "\x00\x0Daccept-ranges\x00"
+"\x00\x06accept\x00"
 "\x00\x1Baccess-control-allow-origin\x00"
 "\x00\x03age\x00"
 "\x00\x05allow\x00"
-"\x00\x0A:authority\x00"
 "\x00\x0Dauthorization\x00"
 "\x00\x0Dcache-control\x00"
 "\x00\x13content-disposition\x00"
@@ -110,7 +138,6 @@
 "\x00\x0Econtent-length\x00"
 "\x00\x10content-location\x00"
 "\x00\x0Dcontent-range\x00"
-"\x00\x0Ccontent-type\x10application/grpc"
 "\x00\x0Ccontent-type\x00"
 "\x00\x06cookie\x00"
 "\x00\x04date\x00"
@@ -118,19 +145,6 @@
 "\x00\x06expect\x00"
 "\x00\x07expires\x00"
 "\x00\x04from\x00"
-"\x00\x14grpc-accept-encoding\x07deflate"
-"\x00\x14grpc-accept-encoding\x0Cdeflate,gzip"
-"\x00\x14grpc-accept-encoding\x04gzip"
-"\x00\x14grpc-accept-encoding\x08identity"
-"\x00\x14grpc-accept-encoding\x10identity,deflate"
-"\x00\x14grpc-accept-encoding\x15identity,deflate,gzip"
-"\x00\x14grpc-accept-encoding\x0Didentity,gzip"
-"\x00\x0Dgrpc-encoding\x07deflate"
-"\x00\x0Dgrpc-encoding\x04gzip"
-"\x00\x0Dgrpc-encoding\x08identity"
-"\x00\x0Bgrpc-status\x010"
-"\x00\x0Bgrpc-status\x011"
-"\x00\x0Bgrpc-status\x012"
 "\x00\x04host\x00"
 "\x00\x08if-match\x00"
 "\x00\x11if-modified-since\x00"
@@ -138,38 +152,29 @@
 "\x00\x08if-range\x00"
 "\x00\x13if-unmodified-since\x00"
 "\x00\x0Dlast-modified\x00"
-"\x00\x0Blb-cost-bin\x00"
 "\x00\x08lb-token\x00"
+"\x00\x0Blb-cost-bin\x00"
 "\x00\x04link\x00"
 "\x00\x08location\x00"
 "\x00\x0Cmax-forwards\x00"
-"\x00\x07:method\x03GET"
-"\x00\x07:method\x04POST"
-"\x00\x07:method\x03PUT"
-"\x00\x05:path\x01/"
-"\x00\x05:path\x0B/index.html"
 "\x00\x12proxy-authenticate\x00"
 "\x00\x13proxy-authorization\x00"
 "\x00\x05range\x00"
 "\x00\x07referer\x00"
 "\x00\x07refresh\x00"
 "\x00\x0Bretry-after\x00"
-"\x00\x07:scheme\x04grpc"
-"\x00\x07:scheme\x04http"
-"\x00\x07:scheme\x05https"
 "\x00\x06server\x00"
 "\x00\x0Aset-cookie\x00"
-"\x00\x07:status\x03200"
-"\x00\x07:status\x03204"
-"\x00\x07:status\x03206"
-"\x00\x07:status\x03304"
-"\x00\x07:status\x03400"
-"\x00\x07:status\x03404"
-"\x00\x07:status\x03500"
 "\x00\x19strict-transport-security\x00"
-"\x00\x02te\x08trailers"
 "\x00\x11transfer-encoding\x00"
 "\x00\x0Auser-agent\x00"
 "\x00\x04vary\x00"
 "\x00\x03via\x00"
 "\x00\x10www-authenticate\x00"
+"\x00\x14grpc-accept-encoding\x08identity"
+"\x00\x14grpc-accept-encoding\x07deflate"
+"\x00\x14grpc-accept-encoding\x10identity,deflate"
+"\x00\x14grpc-accept-encoding\x04gzip"
+"\x00\x14grpc-accept-encoding\x0Didentity,gzip"
+"\x00\x14grpc-accept-encoding\x0Cdeflate,gzip"
+"\x00\x14grpc-accept-encoding\x15identity,deflate,gzip"
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
index 115fb06..186542d 100644
--- a/test/core/end2end/fuzzers/server_fuzzer.c
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -34,6 +34,7 @@
 #include <grpc/grpc.h>
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/surface/server.h"
 #include "test/core/util/memory_counters.h"
 #include "test/core/util/mock_endpoint.h"
@@ -49,7 +50,7 @@
 static void dont_log(gpr_log_func_args *args) {}
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   struct grpc_memory_counters counters;
   if (squelch) gpr_set_log_function(dont_log);
   if (leak_check) grpc_memory_counters_init();
diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c
index cd68b39..65fcb95 100644
--- a/test/core/end2end/goaway_server_test.c
+++ b/test/core/end2end/goaway_server_test.c
@@ -101,8 +101,7 @@
   grpc_metadata_array request_metadata1;
   grpc_call_details request_details1;
   grpc_status_code status1;
-  char *details1 = NULL;
-  size_t details_capacity1 = 0;
+  grpc_slice details1;
   grpc_metadata_array_init(&trailing_metadata_recv1);
   grpc_metadata_array_init(&request_metadata1);
   grpc_call_details_init(&request_details1);
@@ -111,8 +110,7 @@
   grpc_metadata_array request_metadata2;
   grpc_call_details request_details2;
   grpc_status_code status2;
-  char *details2 = NULL;
-  size_t details_capacity2 = 0;
+  grpc_slice details2;
   grpc_metadata_array_init(&trailing_metadata_recv2);
   grpc_metadata_array_init(&request_metadata2);
   grpc_call_details_init(&request_details2);
@@ -137,9 +135,11 @@
   /* create a channel that picks first amongst the servers */
   grpc_channel *chan = grpc_insecure_channel_create("test", &client_args, NULL);
   /* and an initial call to them */
-  grpc_call *call1 = grpc_channel_create_call(
-      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "127.0.0.1",
-      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
+  grpc_slice host = grpc_slice_from_static_string("127.0.0.1");
+  grpc_call *call1 =
+      grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+                               grpc_slice_from_static_string("/foo"), &host,
+                               GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
   /* send initial metadata to probe connectivity */
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -158,7 +158,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
   op->data.recv_status_on_client.status = &status1;
   op->data.recv_status_on_client.status_details = &details1;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity1;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -213,9 +212,10 @@
   cq_verify_empty(cqv);
 
   /* and a new call: should go through to server2 when we start it */
-  grpc_call *call2 = grpc_channel_create_call(
-      chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo", "127.0.0.1",
-      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
+  grpc_call *call2 =
+      grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+                               grpc_slice_from_static_string("/foo"), &host,
+                               GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20), NULL);
   /* send initial metadata to probe connectivity */
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -234,7 +234,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
   op->data.recv_status_on_client.status = &status2;
   op->data.recv_status_on_client.status_details = &details2;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity2;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -300,11 +299,11 @@
   grpc_metadata_array_destroy(&trailing_metadata_recv1);
   grpc_metadata_array_destroy(&request_metadata1);
   grpc_call_details_destroy(&request_details1);
-  gpr_free(details1);
+  grpc_slice_unref(details1);
   grpc_metadata_array_destroy(&trailing_metadata_recv2);
   grpc_metadata_array_destroy(&request_metadata2);
   grpc_call_details_destroy(&request_details2);
-  gpr_free(details2);
+  grpc_slice_unref(details2);
 
   cq_verifier_destroy(cqv);
   grpc_completion_queue_destroy(cq);
diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c
index d974d2c..a9d0287 100644
--- a/test/core/end2end/invalid_call_argument_test.c
+++ b/test/core/end2end/invalid_call_argument_test.c
@@ -56,8 +56,7 @@
   grpc_metadata_array initial_metadata_recv;
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
-  char *details;
-  size_t details_capacity;
+  grpc_slice details;
   grpc_call *server_call;
   grpc_server *server;
   grpc_metadata_array server_initial_metadata_recv;
@@ -76,17 +75,17 @@
   g_state.deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2);
   g_state.cq = grpc_completion_queue_create(NULL);
   g_state.cqv = cq_verifier_create(g_state.cq);
-  g_state.details = NULL;
-  g_state.details_capacity = 0;
+  g_state.details = grpc_empty_slice();
   memset(g_state.ops, 0, sizeof(g_state.ops));
 
   if (is_client) {
     /* create a call, channel to a non existant server */
     g_state.chan =
         grpc_insecure_channel_create("nonexistant:54321", NULL, NULL);
+    grpc_slice host = grpc_slice_from_static_string("nonexistant");
     g_state.call = grpc_channel_create_call(
-        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, "/Foo",
-        "nonexistant", g_state.deadline, NULL);
+        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq,
+        grpc_slice_from_static_string("/Foo"), &host, g_state.deadline, NULL);
   } else {
     g_state.server = grpc_server_create(NULL, NULL);
     grpc_server_register_completion_queue(g_state.server, g_state.cq, NULL);
@@ -97,9 +96,10 @@
     gpr_join_host_port(&server_hostport, "localhost", port);
     g_state.chan = grpc_insecure_channel_create(server_hostport, NULL, NULL);
     gpr_free(server_hostport);
+    grpc_slice host = grpc_slice_from_static_string("bar");
     g_state.call = grpc_channel_create_call(
-        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq, "/Foo", "bar",
-        g_state.deadline, NULL);
+        g_state.chan, NULL, GRPC_PROPAGATE_DEFAULTS, g_state.cq,
+        grpc_slice_from_static_string("/Foo"), &host, g_state.deadline, NULL);
     grpc_metadata_array_init(&g_state.server_initial_metadata_recv);
     grpc_call_details_init(&g_state.call_details);
     op = g_state.ops;
@@ -126,7 +126,7 @@
   grpc_call_destroy(g_state.call);
   cq_verifier_destroy(g_state.cqv);
   grpc_channel_destroy(g_state.chan);
-  gpr_free(g_state.details);
+  grpc_slice_unref(g_state.details);
   grpc_metadata_array_destroy(&g_state.initial_metadata_recv);
   grpc_metadata_array_destroy(&g_state.trailing_metadata_recv);
 
@@ -289,7 +289,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -398,8 +399,6 @@
       &g_state.trailing_metadata_recv;
   op->data.recv_status_on_client.status = &g_state.status;
   op->data.recv_status_on_client.status_details = &g_state.details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &g_state.details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -414,7 +413,6 @@
   op->data.recv_status_on_client.trailing_metadata = NULL;
   op->data.recv_status_on_client.status = NULL;
   op->data.recv_status_on_client.status_details = NULL;
-  op->data.recv_status_on_client.status_details_capacity = NULL;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -453,8 +451,6 @@
       &g_state.trailing_metadata_recv;
   op->data.recv_status_on_client.status = &g_state.status;
   op->data.recv_status_on_client.status_details = &g_state.details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &g_state.details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -474,7 +470,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 1;
   op->reserved = NULL;
   op++;
@@ -495,7 +492,8 @@
   op->data.send_status_from_server.trailing_metadata_count =
       (size_t)INT_MAX + 1;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -515,14 +513,15 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -577,9 +576,8 @@
   gpr_log(GPR_INFO, "test_invalid_initial_metadata_reserved_key");
 
   grpc_metadata metadata;
-  metadata.key = ":start_with_colon";
-  metadata.value = "value";
-  metadata.value_length = 6;
+  metadata.key = grpc_slice_from_static_string(":start_with_colon");
+  metadata.value = grpc_slice_from_static_string("value");
 
   grpc_op *op;
   prepare_test(1);
@@ -599,6 +597,7 @@
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   grpc_init();
+  test_invalid_initial_metadata_reserved_key();
   test_non_null_reserved_on_start_batch();
   test_non_null_reserved_on_op();
   test_send_initial_metadata_more_than_once();
@@ -618,7 +617,6 @@
   test_send_server_status_twice();
   test_recv_close_on_server_with_invalid_flags();
   test_recv_close_on_server_twice();
-  test_invalid_initial_metadata_reserved_key();
   grpc_shutdown();
 
   return 0;
diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c
index 03ff70a..5c0f7a0 100644
--- a/test/core/end2end/no_server_test.c
+++ b/test/core/end2end/no_server_test.c
@@ -52,8 +52,7 @@
   grpc_op *op;
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   grpc_test_init(argc, argv);
   grpc_init();
@@ -65,8 +64,10 @@
 
   /* create a call, channel to a non existant server */
   chan = grpc_insecure_channel_create("nonexistant:54321", NULL, NULL);
+  grpc_slice host = grpc_slice_from_static_string("nonexistant");
   call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Foo", "nonexistant", deadline, NULL);
+                                  grpc_slice_from_static_string("/Foo"), &host,
+                                  deadline, NULL);
 
   memset(ops, 0, sizeof(ops));
   op = ops;
@@ -79,7 +80,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -101,7 +101,7 @@
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
   grpc_shutdown();
diff --git a/test/core/end2end/tests/authority_not_supported.c b/test/core/end2end/tests/authority_not_supported.c
index 705970f..40d217e 100644
--- a/test/core/end2end/tests/authority_not_supported.c
+++ b/test/core/end2end/tests/authority_not_supported.c
@@ -103,9 +103,14 @@
   grpc_byte_buffer *request_payload =
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f =
       begin_test(config, "test_with_authority_header", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -116,11 +121,12 @@
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
+  grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr");
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "foo.test.google.fr", deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -157,7 +163,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -169,7 +174,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_CANCELLED);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c
index e0c7ac7..f18abc7 100644
--- a/test/core/end2end/tests/bad_hostname.c
+++ b/test/core/end2end/tests/bad_hostname.c
@@ -109,11 +109,12 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
+  grpc_slice host = grpc_slice_from_static_string("slartibartfast.local");
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "slartibartfast.local", deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), &host,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -141,7 +142,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -153,7 +153,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/binary_metadata.c b/test/core/end2end/tests/binary_metadata.c
index dd7a8a9..004cc9e 100644
--- a/test/core/end2end/tests/binary_metadata.c
+++ b/test/core/end2end/tests/binary_metadata.c
@@ -110,25 +110,25 @@
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
   grpc_metadata meta_c[2] = {
-      {"key1-bin",
-       "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc",
-       13,
+      {grpc_slice_from_static_string("key1-bin"),
+       grpc_slice_from_static_string(
+           "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc"),
        0,
        {{NULL, NULL, NULL, NULL}}},
-      {"key2-bin",
-       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d",
-       14,
+      {grpc_slice_from_static_string("key2-bin"),
+       grpc_slice_from_static_string(
+           "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"),
        0,
        {{NULL, NULL, NULL, NULL}}}};
   grpc_metadata meta_s[2] = {
-      {"key3-bin",
-       "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee",
-       15,
+      {grpc_slice_from_static_string("key3-bin"),
+       grpc_slice_from_static_string(
+           "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"),
        0,
        {{NULL, NULL, NULL, NULL}}},
-      {"key4-bin",
-       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
-       16,
+      {grpc_slice_from_static_string("key4-bin"),
+       grpc_slice_from_static_string(
+           "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"),
        0,
        {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
@@ -144,13 +144,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -190,7 +190,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -238,7 +237,7 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details =
+  grpc_slice status_string = grpc_slice_from_static_string(
       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12"
       "\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24"
       "\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36"
@@ -253,7 +252,8 @@
       "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8"
       "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea"
       "\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc"
-      "\xfd\xfe\xff";
+      "\xfd\xfe\xff");
+  op->data.send_status_from_server.status_details = &status_string;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -267,24 +267,25 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(
       0 ==
-      strcmp(details,
-             "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
-             "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
-             "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
-             "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
-             "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
-             "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
-             "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
-             "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
-             "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
-             "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
-             "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
-             "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
-             "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
-             "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
-             "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
-             "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+      grpc_slice_str_cmp(
+          details,
+          "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+          "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
+          "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
+          "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
+          "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
+          "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
+          "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
+          "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
+          "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
+          "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
+          "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
+          "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
+          "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
+          "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
+          "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
+          "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -303,7 +304,7 @@
       &initial_metadata_recv, "key4-bin",
       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c
index 606938f..ebc8546 100644
--- a/test/core/end2end/tests/call_creds.c
+++ b/test/core/end2end/tests/call_creds.c
@@ -156,8 +156,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   grpc_call_credentials *creds = NULL;
   grpc_auth_context *s_auth_context = NULL;
@@ -167,8 +166,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
   creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL);
@@ -225,7 +225,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -284,7 +283,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -296,8 +296,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -337,7 +337,7 @@
       break;
   }
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -391,8 +391,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
@@ -404,8 +403,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -425,7 +425,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -468,7 +467,7 @@
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
 
diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c
index a8e310c..a0bec34 100644
--- a/test/core/end2end/tests/cancel_after_accept.c
+++ b/test/core/end2end/tests/cancel_after_accept.c
@@ -43,6 +43,7 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/service_config.h"
 
@@ -118,8 +119,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *request_payload_recv = NULL;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
@@ -154,8 +154,9 @@
   cq_verifier *cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/service/method",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/service/method"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -170,7 +171,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -246,7 +246,7 @@
   grpc_byte_buffer_destroy(response_payload);
   grpc_byte_buffer_destroy(request_payload_recv);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
   grpc_call_destroy(s);
diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c
index 7742f9d..63b8150 100644
--- a/test/core/end2end/tests/cancel_after_client_done.c
+++ b/test/core/end2end/tests/cancel_after_client_done.c
@@ -113,8 +113,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *request_payload_recv = NULL;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
@@ -128,8 +127,9 @@
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -144,7 +144,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -224,7 +223,7 @@
   grpc_byte_buffer_destroy(response_payload);
   grpc_byte_buffer_destroy(request_payload_recv);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
   grpc_call_destroy(s);
diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c
index c3c5418..216c363 100644
--- a/test/core/end2end/tests/cancel_after_invoke.c
+++ b/test/core/end2end/tests/cancel_after_invoke.c
@@ -113,8 +113,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
@@ -122,8 +121,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -138,7 +138,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -183,7 +182,7 @@
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
 
diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c
index d484282..c198fd1 100644
--- a/test/core/end2end/tests/cancel_before_invoke.c
+++ b/test/core/end2end/tests/cancel_before_invoke.c
@@ -111,8 +111,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_byte_buffer *response_payload_recv = NULL;
   grpc_slice request_payload_slice =
       grpc_slice_from_copied_string("hello world");
@@ -120,8 +119,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -138,7 +138,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -181,7 +180,7 @@
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_call_destroy(c);
 
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c
index 5be850b..af91980 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.c
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.c
@@ -106,8 +106,9 @@
   cq_verifier *v_client = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index 3aecaf7..38f8c61 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -108,14 +108,14 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -128,7 +128,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -156,9 +155,9 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c
index d7efe77..847bc1a 100644
--- a/test/core/end2end/tests/compressed_payload.c
+++ b/test/core/end2end/tests/compressed_payload.c
@@ -48,6 +48,7 @@
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/call.h"
 #include "src/core/lib/surface/call_test_only.h"
+#include "src/core/lib/transport/static_metadata.h"
 #include "test/core/end2end/cq_verifier.h"
 
 static void *tag(intptr_t t) { return (void *)t; }
@@ -125,8 +126,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   cq_verifier *cqv;
   char str[1024];
@@ -151,8 +151,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -191,7 +192,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -245,13 +245,13 @@
   gpr_asprintf(&expected_details, "Compression algorithm '%s' is disabled.",
                algo_name);
   /* and we expect a specific reason for it */
-  GPR_ASSERT(0 == strcmp(details, expected_details));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details));
   gpr_free(expected_details);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -305,8 +305,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   cq_verifier *cqv;
   char request_str[1024];
@@ -331,8 +330,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -362,7 +362,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -489,7 +488,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -503,13 +503,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -569,17 +569,14 @@
   grpc_metadata gzip_compression_override;
   grpc_metadata identity_compression_override;
 
-  gzip_compression_override.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
-  gzip_compression_override.value = "gzip";
-  gzip_compression_override.value_length =
-      strlen(gzip_compression_override.value);
+  gzip_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+  gzip_compression_override.value = grpc_slice_from_static_string("gzip");
   memset(&gzip_compression_override.internal_data, 0,
          sizeof(gzip_compression_override.internal_data));
 
-  identity_compression_override.key = GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY;
-  identity_compression_override.value = "identity";
-  identity_compression_override.value_length =
-      strlen(identity_compression_override.value);
+  identity_compression_override.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
+  identity_compression_override.value =
+      grpc_slice_from_static_string("identity");
   memset(&identity_compression_override.internal_data, 0,
          sizeof(identity_compression_override.internal_data));
 
diff --git a/test/core/end2end/tests/default_host.c b/test/core/end2end/tests/default_host.c
index 208e316..0c39957 100644
--- a/test/core/end2end/tests/default_host.c
+++ b/test/core/end2end/tests/default_host.c
@@ -110,13 +110,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", NULL, deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), NULL,
+                               deadline, NULL);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -149,7 +149,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -182,7 +181,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -199,12 +199,12 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
-  GPR_ASSERT(0 == strncmp(call_details.host, "localhost", 9));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+  GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9));
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c
index 8ebf7e6..a013721 100644
--- a/test/core/end2end/tests/disappearing_server.c
+++ b/test/core/end2end/tests/disappearing_server.c
@@ -93,13 +93,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -128,7 +128,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -156,7 +155,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -174,13 +174,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c
index dc8e52a..1b420ad 100644
--- a/test/core/end2end/tests/empty_batch.c
+++ b/test/core/end2end/tests/empty_batch.c
@@ -106,8 +106,9 @@
   grpc_op *op = NULL;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
index ac9d2dd..e91c8aa 100644
--- a/test/core/end2end/tests/filter_call_init_fails.c
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -125,12 +125,12 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -165,7 +165,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -181,9 +180,9 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
-  GPR_ASSERT(0 == strcmp(details, "access denied"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index 45f623c..a1f7d1b 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -121,12 +121,12 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -161,7 +161,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -177,9 +176,10 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED);
-  GPR_ASSERT(0 == strcmp(details, "Failure that's not preventable."));
+  GPR_ASSERT(0 ==
+             grpc_slice_str_cmp(details, "Failure that's not preventable."));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -208,18 +208,12 @@
                           grpc_error *error) {
   grpc_call_element *elem = arg;
   call_data *calld = elem->call_data;
-  if (error == GRPC_ERROR_NONE) {
-    // close the stream with an error.
-    grpc_slice message =
-        grpc_slice_from_copied_string("Failure that's not preventable.");
-    grpc_transport_stream_op *op = grpc_make_transport_stream_op(NULL);
-    grpc_transport_stream_op_add_close(exec_ctx, op,
-                                       GRPC_STATUS_PERMISSION_DENIED, &message);
-    grpc_call_next_op(exec_ctx, elem, op);
-  }
   grpc_closure_sched(
       exec_ctx, calld->recv_im_ready,
-      GRPC_ERROR_CREATE_REFERENCING("Forced call to close", &error, 1));
+      grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING(
+                             "Failure that's not preventable.", &error, 1),
+                         GRPC_ERROR_INT_GRPC_STATUS,
+                         GRPC_STATUS_PERMISSION_DENIED));
 }
 
 static void start_transport_stream_op(grpc_exec_ctx *exec_ctx,
diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c
index dbb5c8d..7f37c46 100644
--- a/test/core/end2end/tests/filter_latency.c
+++ b/test/core/end2end/tests/filter_latency.c
@@ -128,8 +128,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   gpr_mu_lock(&g_mu);
@@ -138,8 +137,10 @@
   gpr_mu_unlock(&g_mu);
   const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
 
-  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/foo", "foo.test.google.fr", deadline, NULL);
+  c = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr", config), deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -173,7 +174,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -198,7 +198,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_string = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_string;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -215,9 +216,9 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c
index 5fecadb..08af25d 100644
--- a/test/core/end2end/tests/graceful_server_shutdown.c
+++ b/test/core/end2end/tests/graceful_server_shutdown.c
@@ -107,13 +107,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -143,7 +143,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -171,7 +170,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -191,12 +191,12 @@
   grpc_call_destroy(s);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/high_initial_seqno.c b/test/core/end2end/tests/high_initial_seqno.c
index 01a4909..217ca2b 100644
--- a/test/core/end2end/tests/high_initial_seqno.c
+++ b/test/core/end2end/tests/high_initial_seqno.c
@@ -113,13 +113,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -148,7 +148,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -172,7 +171,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -189,13 +189,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
index cec8b2f..9aedc9c 100644
--- a/test/core/end2end/tests/hpack_size.c
+++ b/test/core/end2end/tests/hpack_size.c
@@ -254,24 +254,24 @@
   grpc_status_code status;
   grpc_call_error error;
   grpc_metadata extra_metadata[3];
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   memset(extra_metadata, 0, sizeof(extra_metadata));
-  extra_metadata[0].key = "hobbit-first-name";
-  extra_metadata[0].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][0];
-  extra_metadata[0].value_length = strlen(extra_metadata[0].value);
-  extra_metadata[1].key = "hobbit-second-name";
-  extra_metadata[1].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][1];
-  extra_metadata[1].value_length = strlen(extra_metadata[1].value);
-  extra_metadata[2].key = "dragon";
-  extra_metadata[2].value = dragons[index % GPR_ARRAY_SIZE(dragons)];
-  extra_metadata[2].value_length = strlen(extra_metadata[2].value);
+  extra_metadata[0].key = grpc_slice_from_static_string("hobbit-first-name");
+  extra_metadata[0].value = grpc_slice_from_static_string(
+      hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]);
+  extra_metadata[1].key = grpc_slice_from_static_string("hobbit-second-name");
+  extra_metadata[1].value = grpc_slice_from_static_string(
+      hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]);
+  extra_metadata[2].key = grpc_slice_from_static_string("dragon");
+  extra_metadata[2].value =
+      grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -301,7 +301,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -325,7 +324,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -342,13 +342,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/idempotent_request.c b/test/core/end2end/tests/idempotent_request.c
index 4f6d3bb..2db7acc 100644
--- a/test/core/end2end/tests/idempotent_request.c
+++ b/test/core/end2end/tests/idempotent_request.c
@@ -111,14 +111,14 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -152,7 +152,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,7 +184,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -202,14 +202,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c
index 24abfa2..e18953a 100644
--- a/test/core/end2end/tests/invoke_large_request.c
+++ b/test/core/end2end/tests/invoke_large_request.c
@@ -140,13 +140,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -185,7 +185,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -232,7 +231,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -244,13 +244,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c
index 69b4b24..b45ceb2 100644
--- a/test/core/end2end/tests/large_metadata.c
+++ b/test/core/end2end/tests/large_metadata.c
@@ -122,21 +122,19 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
-  meta.key = "key";
-  meta.value = gpr_malloc(large_size + 1);
-  memset((char *)meta.value, 'a', large_size);
-  ((char *)meta.value)[large_size] = 0;
-  meta.value_length = large_size;
+  meta.key = grpc_slice_from_static_string("key");
+  meta.value = grpc_slice_malloc(large_size);
+  memset(GRPC_SLICE_START_PTR(meta.value), 'a', large_size);
 
   grpc_metadata_array_init(&initial_metadata_recv);
   grpc_metadata_array_init(&trailing_metadata_recv);
@@ -170,7 +168,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -216,7 +213,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -228,15 +226,17 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
-  GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value));
+  GPR_ASSERT(contains_metadata_slices(&request_metadata_recv,
+                                      grpc_slice_from_static_string("key"),
+                                      meta.value));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -250,7 +250,7 @@
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(request_payload_recv);
 
-  gpr_free((char *)meta.value);
+  grpc_slice_unref(meta.value);
 
   end_test(&f);
   config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c
index ae5c270..edc4251 100644
--- a/test/core/end2end/tests/load_reporting_hook.c
+++ b/test/core/end2end/tests/load_reporting_hook.c
@@ -146,13 +146,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, method_name,
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string(method_name),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -193,7 +193,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -242,7 +241,8 @@
   op->data.send_status_from_server.trailing_metadata_count = 1;
   op->data.send_status_from_server.trailing_metadata = trailing_lr_metadata;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -255,7 +255,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -295,15 +295,13 @@
   grpc_metadata initial_lr_metadata;
   grpc_metadata trailing_lr_metadata;
 
-  initial_lr_metadata.key = GRPC_LB_TOKEN_MD_KEY;
-  initial_lr_metadata.value = "client-token";
-  initial_lr_metadata.value_length = strlen(initial_lr_metadata.value);
+  initial_lr_metadata.key = GRPC_MDSTR_LB_TOKEN;
+  initial_lr_metadata.value = grpc_slice_from_static_string("client-token");
   memset(&initial_lr_metadata.internal_data, 0,
          sizeof(initial_lr_metadata.internal_data));
 
-  trailing_lr_metadata.key = GRPC_LB_COST_MD_KEY;
-  trailing_lr_metadata.value = "server-token";
-  trailing_lr_metadata.value_length = strlen(trailing_lr_metadata.value);
+  trailing_lr_metadata.key = GRPC_MDSTR_LB_COST_BIN;
+  trailing_lr_metadata.value = grpc_slice_from_static_string("server-token");
   memset(&trailing_lr_metadata.internal_data, 0,
          sizeof(trailing_lr_metadata.internal_data));
 
diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c
index 9338bc5..b34ea40 100644
--- a/test/core/end2end/tests/max_concurrent_streams.c
+++ b/test/core/end2end/tests/max_concurrent_streams.c
@@ -109,13 +109,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -144,7 +144,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -168,7 +167,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,13 +185,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -223,11 +223,9 @@
   grpc_metadata_array trailing_metadata_recv2;
   grpc_status_code status1;
   grpc_call_error error;
-  char *details1 = NULL;
-  size_t details_capacity1 = 0;
+  grpc_slice details1;
   grpc_status_code status2;
-  char *details2 = NULL;
-  size_t details_capacity2 = 0;
+  grpc_slice details2;
   grpc_op ops[6];
   grpc_op *op;
   int was_cancelled;
@@ -261,13 +259,15 @@
      the first completes */
   deadline = n_seconds_time(1000);
   c1 = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/alpha",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/alpha"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c1);
   c2 = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/beta",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/beta"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c2);
 
@@ -295,7 +295,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1;
   op->data.recv_status_on_client.status = &status1;
   op->data.recv_status_on_client.status_details = &details1;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity1;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -327,7 +326,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2;
   op->data.recv_status_on_client.status = &status2;
   op->data.recv_status_on_client.status_details = &details2;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity2;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -378,7 +376,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -392,6 +391,8 @@
   CQ_EXPECT_COMPLETION(cqv, tag(live_call + 1), 1);
   cq_verify(cqv);
 
+  grpc_call_details_destroy(&call_details);
+
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
                                  f.server, &s2, &call_details,
                                  &request_metadata_recv, f.cq, f.cq, tag(201)));
@@ -413,7 +414,7 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -431,8 +432,8 @@
   grpc_call_destroy(c2);
   grpc_call_destroy(s2);
 
-  gpr_free(details1);
-  gpr_free(details2);
+  grpc_slice_unref(details1);
+  grpc_slice_unref(details2);
   grpc_metadata_array_destroy(&initial_metadata_recv1);
   grpc_metadata_array_destroy(&trailing_metadata_recv1);
   grpc_metadata_array_destroy(&initial_metadata_recv2);
diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c
index 4a6ef44..4140df9 100644
--- a/test/core/end2end/tests/max_message_length.c
+++ b/test/core/end2end/tests/max_message_length.c
@@ -43,6 +43,7 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/service_config.h"
 
@@ -129,8 +130,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   grpc_channel_args *client_args = NULL;
@@ -178,8 +178,9 @@
   cqv = cq_verifier_create(f.cq);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/service/method",
-      get_host_override_string("foo.test.google.fr:1234", config),
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/service/method"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
       gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(c);
 
@@ -213,7 +214,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -252,19 +252,20 @@
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.method, "/service/method"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
 done:
   GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
-  GPR_ASSERT(strcmp(details,
-                    send_limit
-                        ? "Sent message larger than max (11 vs. 5)"
-                        : "Received message larger than max (11 vs. 5)") == 0);
+  GPR_ASSERT(
+      grpc_slice_str_cmp(
+          details, send_limit
+                       ? "Sent message larger than max (11 vs. 5)"
+                       : "Received message larger than max (11 vs. 5)") == 0);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
@@ -307,8 +308,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   grpc_channel_args *client_args = NULL;
@@ -354,9 +354,11 @@
   }
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
-                               "/service/method", "foo.test.google.fr:1234",
-                               gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  c = grpc_channel_create_call(
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/service/method"),
+      get_host_override_slice("foo.test.google.fr:1234", config),
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -389,7 +391,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -423,7 +424,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -434,16 +436,18 @@
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  GPR_ASSERT(0 == strcmp(call_details.method, "/service/method"));
-  GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
+  GPR_ASSERT(0 ==
+             grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234"));
 
   GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
-  GPR_ASSERT(strcmp(details,
-                    send_limit
-                        ? "Sent message larger than max (11 vs. 5)"
-                        : "Received message larger than max (11 vs. 5)") == 0);
+  GPR_ASSERT(
+      grpc_slice_str_cmp(
+          details, send_limit
+                       ? "Sent message larger than max (11 vs. 5)"
+                       : "Received message larger than max (11 vs. 5)") == 0);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c
index 929777d..403386b 100644
--- a/test/core/end2end/tests/negative_deadline.c
+++ b/test/core/end2end/tests/negative_deadline.c
@@ -108,14 +108,14 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
 
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -128,7 +128,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -155,7 +154,7 @@
 
   GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c
index 2ebda2c..6cfeaa8 100644
--- a/test/core/end2end/tests/network_status_change.c
+++ b/test/core/end2end/tests/network_status_change.c
@@ -119,13 +119,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -159,7 +159,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -201,7 +200,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -214,11 +214,11 @@
 
   // Expected behavior of a RPC when network is lost.
   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/no_logging.c b/test/core/end2end/tests/no_logging.c
index 54614cb..5c22631 100644
--- a/test/core/end2end/tests/no_logging.c
+++ b/test/core/end2end/tests/no_logging.c
@@ -139,14 +139,14 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -179,7 +179,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -210,7 +209,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -227,14 +227,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c
index 4a88c5f..af0c819 100644
--- a/test/core/end2end/tests/payload.c
+++ b/test/core/end2end/tests/payload.c
@@ -138,13 +138,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -183,7 +183,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -230,7 +229,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -242,8 +242,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -251,7 +251,7 @@
   GPR_ASSERT(
       byte_buffer_eq_slice(response_payload_recv, response_payload_slice));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c
index 0a1566e..b69b7f2 100644
--- a/test/core/end2end/tests/ping_pong_streaming.c
+++ b/test/core/end2end/tests/ping_pong_streaming.c
@@ -112,8 +112,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   grpc_byte_buffer *request_payload;
   grpc_byte_buffer *request_payload_recv;
@@ -126,8 +125,9 @@
       grpc_slice_from_copied_string("hello you");
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -152,7 +152,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -248,7 +247,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -270,7 +270,7 @@
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   end_test(&f);
   config.tear_down_data(&f);
diff --git a/test/core/end2end/tests/registered_call.c b/test/core/end2end/tests/registered_call.c
index 6594b42..e071673 100644
--- a/test/core/end2end/tests/registered_call.c
+++ b/test/core/end2end/tests/registered_call.c
@@ -111,8 +111,7 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_registered_call(
@@ -144,7 +143,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -168,7 +166,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,13 +184,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c
index 9c18e15..1328a7e 100644
--- a/test/core/end2end/tests/request_with_flags.c
+++ b/test/core/end2end/tests/request_with_flags.c
@@ -117,13 +117,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   grpc_call_error expectation;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -157,7 +157,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = flags_for_op[op->op];
   op->reserved = NULL;
   op++;
@@ -168,9 +167,9 @@
   if (expectation == GRPC_CALL_OK) {
     CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
     cq_verify(cqv);
+    grpc_slice_unref(details);
   }
 
-  gpr_free(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c
index c84e3ac..3258c04 100644
--- a/test/core/end2end/tests/request_with_payload.c
+++ b/test/core/end2end/tests/request_with_payload.c
@@ -116,13 +116,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -156,7 +156,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -197,7 +196,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -209,14 +209,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
index c919fae..f65d603 100644
--- a/test/core/end2end/tests/resource_quota_server.c
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -149,8 +149,7 @@
   grpc_call_details *call_details =
       malloc(sizeof(grpc_call_details) * NUM_CALLS);
   grpc_status_code *status = malloc(sizeof(grpc_status_code) * NUM_CALLS);
-  char **details = malloc(sizeof(char *) * NUM_CALLS);
-  size_t *details_capacity = malloc(sizeof(size_t) * NUM_CALLS);
+  grpc_slice *details = malloc(sizeof(grpc_slice) * NUM_CALLS);
   grpc_byte_buffer **request_payload_recv =
       malloc(sizeof(grpc_byte_buffer *) * NUM_CALLS);
   int *was_cancelled = malloc(sizeof(int) * NUM_CALLS);
@@ -173,8 +172,6 @@
     grpc_metadata_array_init(&trailing_metadata_recv[i]);
     grpc_metadata_array_init(&request_metadata_recv[i]);
     grpc_call_details_init(&call_details[i]);
-    details[i] = NULL;
-    details_capacity[i] = 0;
     request_payload_recv[i] = NULL;
     was_cancelled[i] = 0;
   }
@@ -190,8 +187,10 @@
 
   for (int i = 0; i < NUM_CALLS; i++) {
     client_calls[i] = grpc_channel_create_call(
-        f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-        "foo.test.google.fr", n_seconds_time(60), NULL);
+        f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+        grpc_slice_from_static_string("/foo"),
+        get_host_override_slice("foo.test.google.fr", config),
+        n_seconds_time(60), NULL);
 
     memset(ops, 0, sizeof(ops));
     op = ops;
@@ -219,8 +218,6 @@
         &trailing_metadata_recv[i];
     op->data.recv_status_on_client.status = &status[i];
     op->data.recv_status_on_client.status_details = &details[i];
-    op->data.recv_status_on_client.status_details_capacity =
-        &details_capacity[i];
     op->flags = 0;
     op->reserved = NULL;
     op++;
@@ -260,7 +257,7 @@
       grpc_metadata_array_destroy(&initial_metadata_recv[call_id]);
       grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]);
       grpc_call_destroy(client_calls[call_id]);
-      gpr_free(details[call_id]);
+      grpc_slice_unref(details[call_id]);
 
       pending_client_calls--;
     } else if (ev_tag < SERVER_RECV_BASE_TAG) {
@@ -317,7 +314,8 @@
       op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
       op->data.send_status_from_server.trailing_metadata_count = 0;
       op->data.send_status_from_server.status = GRPC_STATUS_OK;
-      op->data.send_status_from_server.status_details = "xyz";
+      grpc_slice status_details = grpc_slice_from_static_string("xyz");
+      op->data.send_status_from_server.status_details = &status_details;
       op->flags = 0;
       op->reserved = NULL;
       op++;
@@ -353,10 +351,6 @@
    * the client has received it. This means that we should see strictly more
    * failures on the client than on the server. */
   GPR_ASSERT(cancelled_calls_on_client >= cancelled_calls_on_server);
-  /* However, we shouldn't see radically more... 0.9 is a guessed bound on what
-   * we'd want that ratio to be... to at least trigger some investigation should
-   * that ratio become much higher. */
-  GPR_ASSERT(cancelled_calls_on_server >= 0.9 * cancelled_calls_on_client);
 
   grpc_byte_buffer_destroy(request_payload);
   grpc_slice_unref(request_payload_slice);
@@ -370,7 +364,6 @@
   free(call_details);
   free(status);
   free(details);
-  free(details_capacity);
   free(request_payload_recv);
   free(was_cancelled);
 
diff --git a/test/core/end2end/tests/server_finishes_request.c b/test/core/end2end/tests/server_finishes_request.c
index 3bb25fd..ee18c68 100644
--- a/test/core/end2end/tests/server_finishes_request.c
+++ b/test/core/end2end/tests/server_finishes_request.c
@@ -111,13 +111,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -142,7 +142,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -166,7 +165,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -183,13 +183,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c
index b80a2e3..0be5315 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.c
+++ b/test/core/end2end/tests/shutdown_finishes_calls.c
@@ -100,13 +100,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -136,7 +136,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -172,12 +171,12 @@
   grpc_server_destroy(f.server);
 
   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_cacheable_request.c b/test/core/end2end/tests/simple_cacheable_request.c
index 2c229b0..ea916e7 100644
--- a/test/core/end2end/tests/simple_cacheable_request.c
+++ b/test/core/end2end/tests/simple_cacheable_request.c
@@ -111,12 +111,22 @@
   grpc_byte_buffer *response_payload =
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_s[2] = {
-      {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+                              grpc_slice_from_static_string("val3"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key4"),
+                              grpc_slice_from_static_string("val4"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
       config, "test_cacheable_request_response_with_metadata_and_payload", NULL,
       NULL);
@@ -131,13 +141,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -177,7 +187,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -225,7 +234,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -237,8 +247,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) {
@@ -254,7 +264,7 @@
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c
index 414a03d..b0c98c5 100644
--- a/test/core/end2end/tests/simple_delayed_request.c
+++ b/test/core/end2end/tests/simple_delayed_request.c
@@ -100,15 +100,15 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   config.init_client(f, client_args);
 
   c = grpc_channel_create_call(
-      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f->client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -137,7 +137,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -163,7 +162,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -180,13 +180,13 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_metadata.c b/test/core/end2end/tests/simple_metadata.c
index 5490cc2..162c89c 100644
--- a/test/core/end2end/tests/simple_metadata.c
+++ b/test/core/end2end/tests/simple_metadata.c
@@ -109,12 +109,22 @@
   grpc_byte_buffer *response_payload =
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_s[2] = {
-      {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+                              grpc_slice_from_static_string("val3"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key4"),
+                              grpc_slice_from_static_string("val4"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
       config, "test_request_response_with_metadata_and_payload", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -128,13 +138,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -174,7 +184,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -222,7 +231,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -234,8 +244,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
@@ -246,7 +256,7 @@
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3"));
   GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index 2dea5d6..e0a6982 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -111,14 +111,14 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
   char *peer;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -152,7 +152,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -185,7 +184,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -202,14 +202,14 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c
index 583bc92..0501252 100644
--- a/test/core/end2end/tests/streaming_error_response.c
+++ b/test/core/end2end/tests/streaming_error_response.c
@@ -121,13 +121,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -154,7 +154,6 @@
     op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
     op->data.recv_status_on_client.status = &status;
     op->data.recv_status_on_client.status_details = &details;
-    op->data.recv_status_on_client.status_details_capacity = &details_capacity;
     op++;
   }
   error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
@@ -202,7 +201,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_FAILED_PRECONDITION;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op++;
   error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL);
   GPR_ASSERT(GRPC_CALL_OK == error);
@@ -232,7 +232,6 @@
     op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
     op->data.recv_status_on_client.status = &status;
     op->data.recv_status_on_client.status_details = &details;
-    op->data.recv_status_on_client.status_details_capacity = &details_capacity;
     op++;
     error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
     GPR_ASSERT(GRPC_CALL_OK == error);
@@ -245,13 +244,13 @@
   }
 
   GPR_ASSERT(status == GRPC_STATUS_FAILED_PRECONDITION);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 1);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/trailing_metadata.c b/test/core/end2end/tests/trailing_metadata.c
index 9fd4fbc..b6741db 100644
--- a/test/core/end2end/tests/trailing_metadata.c
+++ b/test/core/end2end/tests/trailing_metadata.c
@@ -109,15 +109,30 @@
   grpc_byte_buffer *response_payload =
       grpc_raw_byte_buffer_create(&response_payload_slice, 1);
   gpr_timespec deadline = five_seconds_time();
-  grpc_metadata meta_c[2] = {
-      {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_s[2] = {
-      {"key3", "val3", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key4", "val4", 4, 0, {{NULL, NULL, NULL, NULL}}}};
-  grpc_metadata meta_t[2] = {
-      {"key5", "val5", 4, 0, {{NULL, NULL, NULL, NULL}}},
-      {"key6", "val6", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+                              grpc_slice_from_static_string("val1"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key2"),
+                              grpc_slice_from_static_string("val2"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"),
+                              grpc_slice_from_static_string("val3"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key4"),
+                              grpc_slice_from_static_string("val4"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
+  grpc_metadata meta_t[2] = {{grpc_slice_from_static_string("key5"),
+                              grpc_slice_from_static_string("val5"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}},
+                             {grpc_slice_from_static_string("key6"),
+                              grpc_slice_from_static_string("val6"),
+                              0,
+                              {{NULL, NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
       config, "test_request_response_with_metadata_and_payload", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
@@ -131,13 +146,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -177,7 +192,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -226,7 +240,8 @@
   op->data.send_status_from_server.trailing_metadata_count = 2;
   op->data.send_status_from_server.trailing_metadata = meta_t;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -238,8 +253,8 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
@@ -251,7 +266,7 @@
   GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key5", "val5"));
   GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key6", "val6"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/write_buffering.c b/test/core/end2end/tests/write_buffering.c
index 856e9f0..fc17559 100644
--- a/test/core/end2end/tests/write_buffering.c
+++ b/test/core/end2end/tests/write_buffering.c
@@ -120,13 +120,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details = grpc_empty_slice();
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -228,7 +228,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -244,7 +243,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -256,15 +256,15 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123"));
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/end2end/tests/write_buffering_at_end.c b/test/core/end2end/tests/write_buffering_at_end.c
index 43aefcb..6b9a4c5 100644
--- a/test/core/end2end/tests/write_buffering_at_end.c
+++ b/test/core/end2end/tests/write_buffering_at_end.c
@@ -117,13 +117,13 @@
   grpc_call_details call_details;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details = grpc_empty_slice();
   int was_cancelled = 2;
 
   c = grpc_channel_create_call(
-      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), deadline,
+      f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
       NULL);
   GPR_ASSERT(c);
 
@@ -219,7 +219,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -235,7 +234,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.trailing_metadata_count = 0;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
-  op->data.send_status_from_server.status_details = "xyz";
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -247,15 +247,15 @@
   cq_verify(cqv);
 
   GPR_ASSERT(status == GRPC_STATUS_OK);
-  GPR_ASSERT(0 == strcmp(details, "xyz"));
-  GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
   validate_host_override_string("foo.test.google.fr:1234", call_details.host,
                                 config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(request_payload_recv2 == NULL);
 
-  gpr_free(details);
+  grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
   grpc_metadata_array_destroy(&request_metadata_recv);
diff --git a/test/core/fling/client.c b/test/core/fling/client.c
index e717b7f..bb44320 100644
--- a/test/core/fling/client.c
+++ b/test/core/fling/client.c
@@ -57,8 +57,7 @@
 static grpc_metadata_array trailing_metadata_recv;
 static grpc_byte_buffer *response_payload_recv = NULL;
 static grpc_status_code status;
-static char *details = NULL;
-static size_t details_capacity = 0;
+static grpc_slice details;
 static grpc_op *op;
 
 static void init_ping_pong_request(void) {
@@ -86,15 +85,16 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op++;
 }
 
 static void step_ping_pong_request(void) {
   GPR_TIMER_BEGIN("ping_pong", 1);
-  call = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Reflector/reflectUnary", "localhost",
-                                  gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
+  call = grpc_channel_create_call(
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/Reflector/reflectUnary"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call, ops,
                                                    (size_t)(op - ops),
                                                    (void *)1, NULL));
@@ -109,9 +109,11 @@
   grpc_metadata_array_init(&initial_metadata_recv);
 
   grpc_call_error error;
-  call = grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Reflector/reflectStream", "localhost",
-                                  gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  grpc_slice host = grpc_slice_from_static_string("localhost");
+  call = grpc_channel_create_call(
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/Reflector/reflectStream"), &host,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   stream_init_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
   stream_init_ops[0].data.send_initial_metadata.count = 0;
   stream_init_ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index fd446f1..d4849e3 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -118,7 +118,7 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
   op->data.send_status_from_server.trailing_metadata_count = 0;
-  op->data.send_status_from_server.status_details = "";
+  op->data.send_status_from_server.status_details = NULL;
   op++;
   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
   op->data.recv_close_on_server.cancelled = &was_cancelled;
@@ -168,7 +168,7 @@
   status_op[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   status_op[0].data.send_status_from_server.status = GRPC_STATUS_OK;
   status_op[0].data.send_status_from_server.trailing_metadata_count = 0;
-  status_op[0].data.send_status_from_server.status_details = "";
+  status_op[0].data.send_status_from_server.status_details = NULL;
   status_op[1].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
   status_op[1].data.recv_close_on_server.cancelled = &was_cancelled;
 
@@ -259,8 +259,8 @@
         switch ((intptr_t)s) {
           case FLING_SERVER_NEW_REQUEST:
             if (call != NULL) {
-              if (0 ==
-                  strcmp(call_details.method, "/Reflector/reflectStream")) {
+              if (0 == grpc_slice_str_cmp(call_details.method,
+                                          "/Reflector/reflectStream")) {
                 /* Received streaming call. Send metadata here. */
                 start_read_op(FLING_SERVER_READ_FOR_STREAMING);
                 send_initial_metadata();
diff --git a/test/core/iomgr/ev_epoll_linux_test.c b/test/core/iomgr/ev_epoll_linux_test.c
index 40ae91b..0d06f64 100644
--- a/test/core/iomgr/ev_epoll_linux_test.c
+++ b/test/core/iomgr/ev_epoll_linux_test.c
@@ -237,6 +237,7 @@
             "strategy. and the current strategy is: '%s'",
             poll_strategy);
   }
+
   {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
     grpc_iomgr_shutdown(&exec_ctx);
diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c
index f4432bf..0cab872 100644
--- a/test/core/memory_usage/client.c
+++ b/test/core/memory_usage/client.c
@@ -58,8 +58,7 @@
   grpc_call *call;
   grpc_metadata_array initial_metadata_recv;
   grpc_status_code status;
-  char *details;
-  size_t details_capacity;
+  grpc_slice details;
   grpc_metadata_array trailing_metadata_recv;
 } fling_call;
 
@@ -85,9 +84,11 @@
   op->data.recv_initial_metadata = &calls[call_idx].initial_metadata_recv;
   op++;
 
+  grpc_slice hostname = grpc_slice_from_static_string("localhost");
   calls[call_idx].call = grpc_channel_create_call(
-      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/Reflector/reflectUnary",
-      "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+      grpc_slice_from_static_string("/Reflector/reflectUnary"), &hostname,
+      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call,
                                                    metadata_ops,
@@ -107,8 +108,6 @@
       &calls[call_idx].trailing_metadata_recv;
   op->data.recv_status_on_client.status = &calls[call_idx].status;
   op->data.recv_status_on_client.status_details = &calls[call_idx].details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &calls[call_idx].details_capacity;
   op++;
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call,
@@ -118,13 +117,13 @@
   grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv);
   grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv);
-  gpr_free(calls[call_idx].details);
+  grpc_slice_unref(calls[call_idx].details);
   grpc_call_destroy(calls[call_idx].call);
   calls[call_idx].call = NULL;
 }
 
-static struct grpc_memory_counters send_snapshot_request(
-    int call_idx, const char *call_type) {
+static struct grpc_memory_counters send_snapshot_request(int call_idx,
+                                                         grpc_slice call_type) {
   grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv);
   grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv);
 
@@ -149,12 +148,11 @@
       &calls[call_idx].trailing_metadata_recv;
   op->data.recv_status_on_client.status = &calls[call_idx].status;
   op->data.recv_status_on_client.status_details = &calls[call_idx].details;
-  op->data.recv_status_on_client.status_details_capacity =
-      &calls[call_idx].details_capacity;
   op++;
 
+  grpc_slice hostname = grpc_slice_from_static_string("localhost");
   calls[call_idx].call = grpc_channel_create_call(
-      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, "localhost",
+      channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, &hostname,
       gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(
                                  calls[call_idx].call, snapshot_ops,
@@ -184,9 +182,8 @@
   grpc_slice_unref(response);
   grpc_byte_buffer_reader_destroy(&reader);
   grpc_byte_buffer_destroy(response_payload_recv);
-  gpr_free(calls[call_idx].details);
-  calls[call_idx].details = NULL;
-  calls[call_idx].details_capacity = 0;
+  grpc_slice_unref(calls[call_idx].details);
+  calls[call_idx].details = grpc_empty_slice();
   grpc_call_destroy(calls[call_idx].call);
   calls[call_idx].call = NULL;
 
@@ -219,9 +216,8 @@
   gpr_cmdline_parse(cl, argc, argv);
   gpr_cmdline_destroy(cl);
 
-  for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); k++) {
-    calls[k].details = NULL;
-    calls[k].details_capacity = 0;
+  for (size_t k = 0; k < GPR_ARRAY_SIZE(calls); k++) {
+    calls[k].details = grpc_empty_slice();
   }
 
   cq = grpc_completion_queue_create(NULL);
@@ -232,10 +228,10 @@
 
   int call_idx = 0;
 
-  struct grpc_memory_counters before_server_create =
-      send_snapshot_request(0, "Reflector/GetBeforeSvrCreation");
-  struct grpc_memory_counters after_server_create =
-      send_snapshot_request(0, "Reflector/GetAfterSvrCreation");
+  struct grpc_memory_counters before_server_create = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/GetBeforeSvrCreation"));
+  struct grpc_memory_counters after_server_create = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/GetAfterSvrCreation"));
 
   // warmup period
   for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) {
@@ -243,7 +239,8 @@
   }
 
   struct grpc_memory_counters server_benchmark_calls_start =
-      send_snapshot_request(0, "Reflector/SimpleSnapshot");
+      send_snapshot_request(
+          0, grpc_slice_from_static_string("Reflector/SimpleSnapshot"));
 
   struct grpc_memory_counters client_benchmark_calls_start =
       grpc_memory_counters_snapshot();
@@ -256,8 +253,8 @@
   struct grpc_memory_counters client_calls_inflight =
       grpc_memory_counters_snapshot();
 
-  struct grpc_memory_counters server_calls_inflight =
-      send_snapshot_request(0, "Reflector/DestroyCalls");
+  struct grpc_memory_counters server_calls_inflight = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/DestroyCalls"));
 
   do {
     event = grpc_completion_queue_next(
@@ -272,8 +269,8 @@
     finish_ping_pong_request(call_idx + 1);
   }
 
-  struct grpc_memory_counters server_calls_end =
-      send_snapshot_request(0, "Reflector/SimpleSnapshot");
+  struct grpc_memory_counters server_calls_end = send_snapshot_request(
+      0, grpc_slice_from_static_string("Reflector/SimpleSnapshot"));
 
   struct grpc_memory_counters client_channel_end =
       grpc_memory_counters_snapshot();
diff --git a/test/core/memory_usage/server.c b/test/core/memory_usage/server.c
index c071093..e8774bd 100644
--- a/test/core/memory_usage/server.c
+++ b/test/core/memory_usage/server.c
@@ -110,7 +110,8 @@
   status_op.op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   status_op.data.send_status_from_server.status = GRPC_STATUS_OK;
   status_op.data.send_status_from_server.trailing_metadata_count = 0;
-  status_op.data.send_status_from_server.status_details = "";
+  grpc_slice details = grpc_slice_from_static_string("");
+  status_op.data.send_status_from_server.status_details = &details;
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call,
                                                    &status_op, 1, tag, NULL));
@@ -140,7 +141,8 @@
   op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
   op->data.send_status_from_server.status = GRPC_STATUS_OK;
   op->data.send_status_from_server.trailing_metadata_count = 0;
-  op->data.send_status_from_server.status_details = "";
+  grpc_slice details = grpc_slice_from_static_string("");
+  op->data.send_status_from_server.status_details = &details;
   op++;
   op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
   op->data.recv_close_on_server.cancelled = &was_cancelled;
@@ -245,25 +247,27 @@
         switch (s->state) {
           case FLING_SERVER_NEW_REQUEST:
             request_call_unary(++next_call_idx);
-            if (0 ==
-                strcmp(s->call_details.method, "/Reflector/reflectUnary")) {
+            if (0 == grpc_slice_str_cmp(s->call_details.method,
+                                        "/Reflector/reflectUnary")) {
               s->state = FLING_SERVER_SEND_INIT_METADATA;
               send_initial_metadata_unary(s);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/GetBeforeSvrCreation")) {
+            } else if (0 ==
+                       grpc_slice_str_cmp(s->call_details.method,
+                                          "Reflector/GetBeforeSvrCreation")) {
               s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT;
               send_snapshot(s, &before_server_create);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/GetAfterSvrCreation")) {
+            } else if (0 ==
+                       grpc_slice_str_cmp(s->call_details.method,
+                                          "Reflector/GetAfterSvrCreation")) {
               s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT;
               send_snapshot(s, &after_server_create);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/SimpleSnapshot")) {
+            } else if (0 == grpc_slice_str_cmp(s->call_details.method,
+                                               "Reflector/SimpleSnapshot")) {
               s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT;
               current_snapshot = grpc_memory_counters_snapshot();
               send_snapshot(s, &current_snapshot);
-            } else if (0 == strcmp(s->call_details.method,
-                                   "Reflector/DestroyCalls")) {
+            } else if (0 == grpc_slice_str_cmp(s->call_details.method,
+                                               "Reflector/DestroyCalls")) {
               s->state = FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL;
               current_snapshot = grpc_memory_counters_snapshot();
               send_snapshot(s, &current_snapshot);
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 0a79292..c0933c6 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -196,8 +196,8 @@
   grpc_slice value = grpc_slice_from_copied_string(value_str);
   grpc_credentials_md_store_add(store, key, value);
   GPR_ASSERT(store->num_entries == 1);
-  GPR_ASSERT(grpc_slice_cmp(key, store->entries[0].key) == 0);
-  GPR_ASSERT(grpc_slice_cmp(value, store->entries[0].value) == 0);
+  GPR_ASSERT(grpc_slice_eq(key, store->entries[0].key));
+  GPR_ASSERT(grpc_slice_eq(value, store->entries[0].value));
   grpc_slice_unref(key);
   grpc_slice_unref(value);
   grpc_credentials_md_store_unref(&exec_ctx, store);
@@ -1065,9 +1065,8 @@
   *s = PLUGIN_GET_METADATA_CALLED_STATE;
   for (i = 0; i < GPR_ARRAY_SIZE(plugin_md); i++) {
     memset(&md[i], 0, sizeof(grpc_metadata));
-    md[i].key = plugin_md[i].key;
-    md[i].value = plugin_md[i].value;
-    md[i].value_length = strlen(plugin_md[i].value);
+    md[i].key = grpc_slice_from_copied_string(plugin_md[i].key);
+    md[i].value = grpc_slice_from_copied_string(plugin_md[i].value);
   }
   cb(user_data, md, GPR_ARRAY_SIZE(md), GRPC_STATUS_OK, NULL);
 }
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index 2b74690..ea136fb 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -63,7 +63,7 @@
   } else {
     char *token;
     GPR_ASSERT(num_md == 1);
-    token = grpc_dump_slice(md_elems[0].value, GPR_DUMP_ASCII);
+    token = grpc_slice_to_c_string(md_elems[0].value);
     printf("\nGot token: %s\n\n", token);
     gpr_free(token);
   }
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index e1d6ff9..bcc50d0 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -164,7 +164,7 @@
   grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(n == 1);
   GPR_ASSERT(incoming.count == 1);
-  GPR_ASSERT(0 == grpc_slice_cmp(s, incoming.slices[0]));
+  GPR_ASSERT(grpc_slice_eq(s, incoming.slices[0]));
 
   grpc_endpoint_shutdown(&exec_ctx, f.client_ep);
   grpc_endpoint_shutdown(&exec_ctx, f.server_ep);
diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c
index 8872cbe..4219b13 100644
--- a/test/core/security/security_connector_test.c
+++ b/test/core/security/security_connector_test.c
@@ -370,7 +370,7 @@
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
   grpc_set_ssl_roots_override_callback(override_roots_success);
   grpc_slice roots = grpc_get_default_ssl_roots_for_testing();
-  char *roots_contents = grpc_dump_slice(roots, GPR_DUMP_ASCII);
+  char *roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
   gpr_free(roots_contents);
@@ -379,7 +379,7 @@
      instead. */
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path);
   roots = grpc_get_default_ssl_roots_for_testing();
-  roots_contents = grpc_dump_slice(roots, GPR_DUMP_ASCII);
+  roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0);
   gpr_free(roots_contents);
@@ -388,7 +388,7 @@
      the api. */
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
   roots = grpc_get_default_ssl_roots_for_testing();
-  roots_contents = grpc_dump_slice(roots, GPR_DUMP_ASCII);
+  roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
   gpr_free(roots_contents);
diff --git a/test/core/slice/percent_encode_fuzzer.c b/test/core/slice/percent_encode_fuzzer.c
index 9698e79..0d440c5 100644
--- a/test/core/slice/percent_encode_fuzzer.c
+++ b/test/core/slice/percent_encode_fuzzer.c
@@ -55,8 +55,8 @@
   grpc_slice permissive_decoded_output =
       grpc_permissive_percent_decode_slice(output);
   // and decoded output must always match the input
-  GPR_ASSERT(grpc_slice_cmp(input, decoded_output) == 0);
-  GPR_ASSERT(grpc_slice_cmp(input, permissive_decoded_output) == 0);
+  GPR_ASSERT(grpc_slice_eq(input, decoded_output));
+  GPR_ASSERT(grpc_slice_eq(input, permissive_decoded_output));
   grpc_slice_unref(input);
   grpc_slice_unref(output);
   grpc_slice_unref(decoded_output);
diff --git a/test/core/slice/percent_encoding_test.c b/test/core/slice/percent_encoding_test.c
index d71c99f..222e695 100644
--- a/test/core/slice/percent_encoding_test.c
+++ b/test/core/slice/percent_encoding_test.c
@@ -81,9 +81,9 @@
   gpr_free(encoded2raw_msg);
   gpr_free(encoded2raw_permissive_msg);
 
-  GPR_ASSERT(0 == grpc_slice_cmp(raw_slice, encoded2raw_slice));
-  GPR_ASSERT(0 == grpc_slice_cmp(raw_slice, encoded2raw_permissive_slice));
-  GPR_ASSERT(0 == grpc_slice_cmp(encoded_slice, raw2encoded_slice));
+  GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_slice));
+  GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_permissive_slice));
+  GPR_ASSERT(grpc_slice_eq(encoded_slice, raw2encoded_slice));
 
   grpc_slice_unref(encoded2raw_slice);
   grpc_slice_unref(encoded2raw_permissive_slice);
@@ -123,8 +123,8 @@
           encoded2raw_permissive_msg);
   gpr_free(encoded2raw_permissive_msg);
 
-  GPR_ASSERT(0 == grpc_slice_cmp(permissive_unencoded_slice,
-                                 encoded2raw_permissive_slice));
+  GPR_ASSERT(
+      grpc_slice_eq(permissive_unencoded_slice, encoded2raw_permissive_slice));
 
   grpc_slice_unref(permissive_unencoded_slice);
   grpc_slice_unref(encoded2raw_permissive_slice);
diff --git a/test/core/slice/slice_test.c b/test/core/slice/slice_test.c
index ca44bec..f68a953 100644
--- a/test/core/slice/slice_test.c
+++ b/test/core/slice/slice_test.c
@@ -35,8 +35,12 @@
 
 #include <string.h>
 
+#include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST_NAME(x) gpr_log(GPR_INFO, "%s", x);
@@ -61,8 +65,10 @@
     GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == length);
     /* If the slice has a refcount, it must be destroyable. */
     if (slice.refcount) {
-      GPR_ASSERT(slice.refcount->ref != NULL);
-      GPR_ASSERT(slice.refcount->unref != NULL);
+      GPR_ASSERT(slice.refcount->vtable != NULL);
+      GPR_ASSERT(slice.refcount->vtable->ref != NULL);
+      GPR_ASSERT(slice.refcount->vtable->unref != NULL);
+      GPR_ASSERT(slice.refcount->vtable->hash != NULL);
     }
     /* We must be able to write to every byte of the data */
     for (i = 0; i < length; i++) {
@@ -249,6 +255,55 @@
   grpc_slice_unref(slice);
 }
 
+static void test_slice_interning(void) {
+  LOG_TEST_NAME("test_slice_interning");
+
+  grpc_init();
+  grpc_slice src1 = grpc_slice_from_copied_string("hello123456789123456789");
+  grpc_slice src2 = grpc_slice_from_copied_string("hello123456789123456789");
+  GPR_ASSERT(GRPC_SLICE_START_PTR(src1) != GRPC_SLICE_START_PTR(src2));
+  grpc_slice interned1 = grpc_slice_intern(src1);
+  grpc_slice interned2 = grpc_slice_intern(src2);
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) ==
+             GRPC_SLICE_START_PTR(interned2));
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned1) != GRPC_SLICE_START_PTR(src1));
+  GPR_ASSERT(GRPC_SLICE_START_PTR(interned2) != GRPC_SLICE_START_PTR(src2));
+  grpc_slice_unref(src1);
+  grpc_slice_unref(src2);
+  grpc_slice_unref(interned1);
+  grpc_slice_unref(interned2);
+  grpc_shutdown();
+}
+
+static void test_static_slice_interning(void) {
+  LOG_TEST_NAME("test_static_slice_interning");
+
+  // grpc_init/grpc_shutdown deliberately omitted: they should not be necessary
+  // to intern a static slice
+
+  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    GPR_ASSERT(grpc_slice_is_equivalent(
+        grpc_static_slice_table[i],
+        grpc_slice_intern(grpc_static_slice_table[i])));
+  }
+}
+
+static void test_static_slice_copy_interning(void) {
+  LOG_TEST_NAME("test_static_slice_copy_interning");
+
+  grpc_init();
+
+  for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) {
+    grpc_slice copy = grpc_slice_dup(grpc_static_slice_table[i]);
+    GPR_ASSERT(grpc_static_slice_table[i].refcount != copy.refcount);
+    GPR_ASSERT(grpc_static_slice_table[i].refcount ==
+               grpc_slice_intern(copy).refcount);
+    grpc_slice_unref(copy);
+  }
+
+  grpc_shutdown();
+}
+
 int main(int argc, char **argv) {
   unsigned length;
   grpc_test_init(argc, argv);
@@ -262,5 +317,8 @@
     test_slice_split_tail_works(length);
   }
   test_slice_from_copied_string_works();
+  test_slice_interning();
+  test_static_slice_interning();
+  test_static_slice_copy_interning();
   return 0;
 }
diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c
index b6db6a6..a2e1030 100644
--- a/test/core/surface/lame_client_test.c
+++ b/test/core/surface/lame_client_test.c
@@ -90,8 +90,7 @@
   grpc_metadata_array trailing_metadata_recv;
   grpc_status_code status;
   grpc_call_error error;
-  char *details = NULL;
-  size_t details_capacity = 0;
+  grpc_slice details;
   char *peer;
 
   grpc_test_init(argc, argv);
@@ -111,8 +110,9 @@
 
   cq = grpc_completion_queue_create(NULL);
 
+  grpc_slice host = grpc_slice_from_static_string("anywhere");
   call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                                  "/Foo", "anywhere",
+                                  grpc_slice_from_static_string("/Foo"), &host,
                                   GRPC_TIMEOUT_SECONDS_TO_DEADLINE(100), NULL);
   GPR_ASSERT(call);
   cqv = cq_verifier_create(cq);
@@ -142,7 +142,6 @@
   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
   op->data.recv_status_on_client.status = &status;
   op->data.recv_status_on_client.status_details = &details;
-  op->data.recv_status_on_client.status_details_capacity = &details_capacity;
   op->flags = 0;
   op->reserved = NULL;
   op++;
@@ -164,7 +163,7 @@
 
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
-  gpr_free(details);
+  grpc_slice_unref(details);
 
   grpc_shutdown();
 
diff --git a/test/core/transport/chttp2/bin_decoder_test.c b/test/core/transport/chttp2/bin_decoder_test.c
index 221112a..a8b0a75 100644
--- a/test/core/transport/chttp2/bin_decoder_test.c
+++ b/test/core/transport/chttp2/bin_decoder_test.c
@@ -46,7 +46,7 @@
 
 static void expect_slice_eq(grpc_exec_ctx *exec_ctx, grpc_slice expected,
                             grpc_slice slice, char *debug, int line) {
-  if (0 != grpc_slice_cmp(slice, expected)) {
+  if (!grpc_slice_eq(slice, expected)) {
     char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot:  %s\nwant: %s", line, debug, hs,
diff --git a/test/core/transport/chttp2/bin_encoder_test.c b/test/core/transport/chttp2/bin_encoder_test.c
index 53b55a3..bd10a1e 100644
--- a/test/core/transport/chttp2/bin_encoder_test.c
+++ b/test/core/transport/chttp2/bin_encoder_test.c
@@ -48,7 +48,7 @@
 
 static void expect_slice_eq(grpc_slice expected, grpc_slice slice, char *debug,
                             int line) {
-  if (0 != grpc_slice_cmp(slice, expected)) {
+  if (!grpc_slice_eq(slice, expected)) {
     char *hs = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *he = grpc_dump_slice(expected, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     gpr_log(GPR_ERROR, "FAILED:%d: %s\ngot:  %s\nwant: %s", line, debug, hs,
@@ -84,8 +84,8 @@
   grpc_slice input = grpc_slice_from_copied_buffer(s, len);
   grpc_slice base64 = grpc_chttp2_base64_encode(input);
   grpc_slice expect = grpc_chttp2_huffman_compress(base64);
-  grpc_slice got = grpc_chttp2_base64_encode_and_huffman_compress_impl(input);
-  if (0 != grpc_slice_cmp(expect, got)) {
+  grpc_slice got = grpc_chttp2_base64_encode_and_huffman_compress(input);
+  if (!grpc_slice_eq(expect, got)) {
     char *t = grpc_dump_slice(input, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *e = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *g = grpc_dump_slice(got, GPR_DUMP_HEX | GPR_DUMP_ASCII);
@@ -106,7 +106,7 @@
   expect_combined_equiv(x, sizeof(x) - 1, __LINE__)
 
 static void expect_binary_header(const char *hdr, int binary) {
-  if (grpc_is_binary_header(hdr, strlen(hdr)) != binary) {
+  if (grpc_is_binary_header(grpc_slice_from_static_string(hdr)) != binary) {
     gpr_log(GPR_ERROR, "FAILED: expected header '%s' to be %s", hdr,
             binary ? "binary" : "not binary");
     all_ok = 0;
diff --git a/test/core/transport/chttp2/hpack_encoder_test.c b/test/core/transport/chttp2/hpack_encoder_test.c
index 1fd2540..d572d79 100644
--- a/test/core/transport/chttp2/hpack_encoder_test.c
+++ b/test/core/transport/chttp2/hpack_encoder_test.c
@@ -81,7 +81,9 @@
       e[i - 1].next = &e[i];
       e[i].prev = &e[i - 1];
     }
-    e[i].md = grpc_mdelem_from_strings(exec_ctx, key, value);
+    e[i].md = grpc_mdelem_from_slices(
+        exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)),
+        grpc_slice_intern(grpc_slice_from_static_string(value)));
   }
   e[0].prev = NULL;
   e[nheaders - 1].next = NULL;
@@ -89,6 +91,7 @@
 
   b.list.head = &e[0];
   b.list.tail = &e[nheaders - 1];
+  b.list.count = nheaders;
 
   if (cap_to_delete == num_to_delete) {
     cap_to_delete = GPR_MAX(2 * cap_to_delete, 1000);
@@ -106,7 +109,7 @@
   grpc_slice_buffer_destroy_internal(exec_ctx, &output);
   grpc_metadata_batch_destroy(exec_ctx, &b);
 
-  if (0 != grpc_slice_cmp(merged, expect)) {
+  if (!grpc_slice_eq(merged, expect)) {
     char *expect_str = grpc_dump_slice(expect, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     char *got_str = grpc_dump_slice(merged, GPR_DUMP_HEX | GPR_DUMP_ASCII);
     gpr_log(GPR_ERROR, "mismatched output for %s", expected);
@@ -193,7 +196,9 @@
                                                      const char *key,
                                                      const char *value) {
   grpc_slice_buffer output;
-  grpc_mdelem *elem = grpc_mdelem_from_strings(exec_ctx, key, value);
+  grpc_mdelem elem = grpc_mdelem_from_slices(
+      exec_ctx, grpc_slice_intern(grpc_slice_from_static_string(key)),
+      grpc_slice_intern(grpc_slice_from_static_string(value)));
   size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
   size_t initial_table_size = g_compressor.table_size;
   grpc_linked_mdelem *e = gpr_malloc(sizeof(*e));
@@ -204,6 +209,7 @@
   e[0].next = NULL;
   b.list.head = &e[0];
   b.list.tail = &e[0];
+  b.list.count = 1;
   grpc_slice_buffer_init(&output);
 
   grpc_transport_one_way_stats stats;
@@ -233,7 +239,7 @@
 
 int main(int argc, char **argv) {
   size_t i;
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   grpc_test_init(argc, argv);
   grpc_init();
   TEST(test_basic_headers);
diff --git a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
index 4e00f49..e9ac16d 100644
--- a/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
+++ b/test/core/transport/chttp2/hpack_parser_fuzzer_test.c
@@ -39,25 +39,26 @@
 #include <grpc/support/log.h>
 
 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
+#include "src/core/lib/slice/slice_internal.h"
 
 bool squelch = true;
 bool leak_check = true;
 
-static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem *md) {
+static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) {
   GRPC_MDELEM_UNREF(exec_ctx, md);
 }
 static void dont_log(gpr_log_func_args *args) {}
 
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-  grpc_test_only_set_metadata_hash_seed(0);
+  grpc_test_only_set_slice_hash_seed(0);
   if (squelch) gpr_set_log_function(dont_log);
   grpc_init();
   grpc_chttp2_hpack_parser parser;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_chttp2_hpack_parser_init(&exec_ctx, &parser);
   parser.on_header = onhdr;
-  GRPC_ERROR_UNREF(
-      grpc_chttp2_hpack_parser_parse(&exec_ctx, &parser, data, data + size));
+  GRPC_ERROR_UNREF(grpc_chttp2_hpack_parser_parse(
+      &exec_ctx, &parser, grpc_slice_from_static_buffer(data, size)));
   grpc_chttp2_hpack_parser_destroy(&exec_ctx, &parser);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
diff --git a/test/core/transport/chttp2/hpack_parser_test.c b/test/core/transport/chttp2/hpack_parser_test.c
index 8f48849..01789c4 100644
--- a/test/core/transport/chttp2/hpack_parser_test.c
+++ b/test/core/transport/chttp2/hpack_parser_test.c
@@ -45,15 +45,15 @@
 
 typedef struct { va_list args; } test_checker;
 
-static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem *md) {
+static void onhdr(grpc_exec_ctx *exec_ctx, void *ud, grpc_mdelem md) {
   const char *ekey, *evalue;
   test_checker *chk = ud;
   ekey = va_arg(chk->args, char *);
   GPR_ASSERT(ekey);
   evalue = va_arg(chk->args, char *);
   GPR_ASSERT(evalue);
-  GPR_ASSERT(grpc_slice_str_cmp(md->key->slice, ekey) == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(md->value->slice, evalue) == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(md), ekey) == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(md), evalue) == 0);
   GRPC_MDELEM_UNREF(exec_ctx, md);
 }
 
@@ -76,9 +76,8 @@
 
   for (i = 0; i < nslices; i++) {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    GPR_ASSERT(grpc_chttp2_hpack_parser_parse(
-                   &exec_ctx, parser, GRPC_SLICE_START_PTR(slices[i]),
-                   GRPC_SLICE_END_PTR(slices[i])) == GRPC_ERROR_NONE);
+    GPR_ASSERT(grpc_chttp2_hpack_parser_parse(&exec_ctx, parser, slices[i]) ==
+               GRPC_ERROR_NONE);
     grpc_exec_ctx_finish(&exec_ctx);
   }
 
diff --git a/test/core/transport/chttp2/hpack_table_test.c b/test/core/transport/chttp2/hpack_table_test.c
index ef2ad66..d2f6d5d 100644
--- a/test/core/transport/chttp2/hpack_table_test.c
+++ b/test/core/transport/chttp2/hpack_table_test.c
@@ -46,16 +46,16 @@
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
 
-static void assert_str(const grpc_chttp2_hptbl *tbl, grpc_mdstr *mdstr,
+static void assert_str(const grpc_chttp2_hptbl *tbl, grpc_slice mdstr,
                        const char *str) {
-  GPR_ASSERT(grpc_slice_str_cmp(mdstr->slice, str) == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(mdstr, str) == 0);
 }
 
 static void assert_index(const grpc_chttp2_hptbl *tbl, uint32_t idx,
                          const char *key, const char *value) {
-  grpc_mdelem *md = grpc_chttp2_hptbl_lookup(tbl, idx);
-  assert_str(tbl, md->key, key);
-  assert_str(tbl, md->value, value);
+  grpc_mdelem md = grpc_chttp2_hptbl_lookup(tbl, idx);
+  assert_str(tbl, GRPC_MDKEY(md), key);
+  assert_str(tbl, GRPC_MDVALUE(md), value);
 }
 
 static void test_static_lookup(void) {
@@ -143,10 +143,12 @@
   grpc_chttp2_hptbl_init(&exec_ctx, &tbl);
 
   for (i = 0; i < 100000; i++) {
-    grpc_mdelem *elem;
+    grpc_mdelem elem;
     gpr_asprintf(&key, "K:%d", i);
     gpr_asprintf(&value, "VALUE:%d", i);
-    elem = grpc_mdelem_from_strings(&exec_ctx, key, value);
+    elem =
+        grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key),
+                                grpc_slice_from_copied_string(value));
     GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
     GRPC_MDELEM_UNREF(&exec_ctx, elem);
     assert_index(&tbl, 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY, key, value);
@@ -169,7 +171,9 @@
                                                  const char *key,
                                                  const char *value) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_mdelem *md = grpc_mdelem_from_strings(&exec_ctx, key, value);
+  grpc_mdelem md =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_copied_string(key),
+                              grpc_slice_from_copied_string(value));
   grpc_chttp2_hptbl_find_result r = grpc_chttp2_hptbl_find(tbl, md);
   GRPC_MDELEM_UNREF(&exec_ctx, md);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -181,19 +185,24 @@
   grpc_chttp2_hptbl tbl;
   uint32_t i;
   char buffer[32];
-  grpc_mdelem *elem;
+  grpc_mdelem elem;
   grpc_chttp2_hptbl_find_result r;
 
   LOG_TEST("test_find");
 
   grpc_chttp2_hptbl_init(&exec_ctx, &tbl);
-  elem = grpc_mdelem_from_strings(&exec_ctx, "abc", "xyz");
+  elem =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"),
+                              grpc_slice_from_static_string("xyz"));
   GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(&exec_ctx, elem);
-  elem = grpc_mdelem_from_strings(&exec_ctx, "abc", "123");
+  elem =
+      grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("abc"),
+                              grpc_slice_from_static_string("123"));
   GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(&exec_ctx, elem);
-  elem = grpc_mdelem_from_strings(&exec_ctx, "x", "1");
+  elem = grpc_mdelem_from_slices(&exec_ctx, grpc_slice_from_static_string("x"),
+                                 grpc_slice_from_static_string("1"));
   GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
   GRPC_MDELEM_UNREF(&exec_ctx, elem);
 
@@ -244,7 +253,9 @@
   /* overflow the string buffer, check find still works */
   for (i = 0; i < 10000; i++) {
     int64_ttoa(i, buffer);
-    elem = grpc_mdelem_from_strings(&exec_ctx, "test", buffer);
+    elem = grpc_mdelem_from_slices(&exec_ctx,
+                                   grpc_slice_from_static_string("test"),
+                                   grpc_slice_from_copied_string(buffer));
     GPR_ASSERT(grpc_chttp2_hptbl_add(&exec_ctx, &tbl, elem) == GRPC_ERROR_NONE);
     GRPC_MDELEM_UNREF(&exec_ctx, elem);
   }
diff --git a/test/core/transport/chttp2/varint_test.c b/test/core/transport/chttp2/varint_test.c
index e29be4b..f12c340 100644
--- a/test/core/transport/chttp2/varint_test.c
+++ b/test/core/transport/chttp2/varint_test.c
@@ -49,7 +49,7 @@
   slice = grpc_slice_malloc(nbytes);
   GRPC_CHTTP2_WRITE_VARINT(value, prefix_bits, prefix_or,
                            GRPC_SLICE_START_PTR(slice), nbytes);
-  GPR_ASSERT(grpc_slice_cmp(expect, slice) == 0);
+  GPR_ASSERT(grpc_slice_eq(expect, slice));
   grpc_slice_unref(expect);
   grpc_slice_unref(slice);
 }
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index 3625043..92e58f2 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -47,55 +47,51 @@
 #include "src/core/lib/transport/static_metadata.h"
 #include "test/core/util/test_config.h"
 
-#define LOG_TEST(x) gpr_log(GPR_INFO, "%s", x)
-
 /* a large number */
 #define MANY 10000
 
 static void test_no_op(void) {
-  LOG_TEST("test_no_op");
+  gpr_log(GPR_INFO, "test_no_op");
   grpc_init();
   grpc_shutdown();
 }
 
-static void test_create_string(void) {
-  grpc_mdstr *s1, *s2, *s3;
-
-  LOG_TEST("test_create_string");
-
-  grpc_init();
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  s1 = grpc_mdstr_from_string("hello");
-  s2 = grpc_mdstr_from_string("hello");
-  s3 = grpc_mdstr_from_string("very much not hello");
-  GPR_ASSERT(s1 == s2);
-  GPR_ASSERT(s3 != s1);
-  GPR_ASSERT(grpc_slice_str_cmp(s1->slice, "hello") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(s3->slice, "very much not hello") == 0);
-  GRPC_MDSTR_UNREF(&exec_ctx, s1);
-  GRPC_MDSTR_UNREF(&exec_ctx, s2);
-  GRPC_MDSTR_UNREF(&exec_ctx, s3);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
+static grpc_slice maybe_intern(grpc_slice in, bool intern) {
+  grpc_slice out = intern ? grpc_slice_intern(in) : grpc_slice_ref(in);
+  grpc_slice_unref(in);
+  return out;
 }
 
-static void test_create_metadata(void) {
-  grpc_mdelem *m1, *m2, *m3;
+static grpc_slice maybe_dup(grpc_slice in, bool dup) {
+  grpc_slice out = dup ? grpc_slice_dup(in) : grpc_slice_ref(in);
+  grpc_slice_unref(in);
+  return out;
+}
 
-  LOG_TEST("test_create_metadata");
+static void test_create_metadata(bool intern_keys, bool intern_values) {
+  grpc_mdelem m1, m2, m3;
+
+  gpr_log(GPR_INFO, "test_create_metadata: intern_keys=%d intern_values=%d",
+          intern_keys, intern_values);
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  m1 = grpc_mdelem_from_strings(&exec_ctx, "a", "b");
-  m2 = grpc_mdelem_from_strings(&exec_ctx, "a", "b");
-  m3 = grpc_mdelem_from_strings(&exec_ctx, "a", "c");
-  GPR_ASSERT(m1 == m2);
-  GPR_ASSERT(m3 != m1);
-  GPR_ASSERT(m3->key == m1->key);
-  GPR_ASSERT(m3->value != m1->value);
-  GPR_ASSERT(grpc_slice_str_cmp(m1->key->slice, "a") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(m1->value->slice, "b") == 0);
-  GPR_ASSERT(grpc_slice_str_cmp(m3->value->slice, "c") == 0);
+  m1 = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  m2 = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  m3 = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("c"), intern_values));
+  GPR_ASSERT(grpc_mdelem_eq(m1, m2));
+  GPR_ASSERT(!grpc_mdelem_eq(m3, m1));
+  GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(m3), GRPC_MDKEY(m1)));
+  GPR_ASSERT(!grpc_slice_eq(GRPC_MDVALUE(m3), GRPC_MDVALUE(m1)));
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDKEY(m1), "a") == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m1), "b") == 0);
+  GPR_ASSERT(grpc_slice_str_cmp(GRPC_MDVALUE(m3), "c") == 0);
   GRPC_MDELEM_UNREF(&exec_ctx, m1);
   GRPC_MDELEM_UNREF(&exec_ctx, m2);
   GRPC_MDELEM_UNREF(&exec_ctx, m3);
@@ -103,19 +99,28 @@
   grpc_shutdown();
 }
 
-static void test_create_many_ephemeral_metadata(void) {
+static void test_create_many_ephemeral_metadata(bool intern_keys,
+                                                bool intern_values) {
   char buffer[GPR_LTOA_MIN_BUFSIZE];
   long i;
 
-  LOG_TEST("test_create_many_ephemeral_metadata");
+  gpr_log(
+      GPR_INFO,
+      "test_create_many_ephemeral_metadata: intern_keys=%d intern_values=%d",
+      intern_keys, intern_values);
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   /* add, and immediately delete a bunch of different elements */
   for (i = 0; i < MANY; i++) {
     gpr_ltoa(i, buffer);
-    GRPC_MDELEM_UNREF(&exec_ctx,
-                      grpc_mdelem_from_strings(&exec_ctx, "a", buffer));
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_from_slices(
+            &exec_ctx,
+            maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+            maybe_intern(grpc_slice_from_copied_string(buffer),
+                         intern_values)));
   }
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
@@ -124,23 +129,27 @@
 static void test_create_many_persistant_metadata(void) {
   char buffer[GPR_LTOA_MIN_BUFSIZE];
   long i;
-  grpc_mdelem **created = gpr_malloc(sizeof(grpc_mdelem *) * MANY);
-  grpc_mdelem *md;
+  grpc_mdelem *created = gpr_malloc(sizeof(grpc_mdelem) * MANY);
+  grpc_mdelem md;
 
-  LOG_TEST("test_create_many_persistant_metadata");
+  gpr_log(GPR_INFO, "test_create_many_persistant_metadata");
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   /* add phase */
   for (i = 0; i < MANY; i++) {
     gpr_ltoa(i, buffer);
-    created[i] = grpc_mdelem_from_strings(&exec_ctx, "a", buffer);
+    created[i] = grpc_mdelem_from_slices(
+        &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")),
+        grpc_slice_intern(grpc_slice_from_static_string(buffer)));
   }
   /* verify phase */
   for (i = 0; i < MANY; i++) {
     gpr_ltoa(i, buffer);
-    md = grpc_mdelem_from_strings(&exec_ctx, "a", buffer);
-    GPR_ASSERT(md == created[i]);
+    md = grpc_mdelem_from_slices(
+        &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("a")),
+        grpc_slice_intern(grpc_slice_from_static_string(buffer)));
+    GPR_ASSERT(grpc_mdelem_eq(md, created[i]));
     GRPC_MDELEM_UNREF(&exec_ctx, md);
   }
   /* cleanup phase */
@@ -153,14 +162,77 @@
   gpr_free(created);
 }
 
-static void test_spin_creating_the_same_thing(void) {
-  LOG_TEST("test_spin_creating_the_same_thing");
+static void test_spin_creating_the_same_thing(bool intern_keys,
+                                              bool intern_values) {
+  gpr_log(GPR_INFO,
+          "test_spin_creating_the_same_thing: intern_keys=%d intern_values=%d",
+          intern_keys, intern_values);
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_from_strings(&exec_ctx, "a", "b"));
-  GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_from_strings(&exec_ctx, "a", "b"));
-  GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_from_strings(&exec_ctx, "a", "b"));
+  grpc_mdelem a, b, c;
+  GRPC_MDELEM_UNREF(
+      &exec_ctx,
+      a = grpc_mdelem_from_slices(
+          &exec_ctx,
+          maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+          maybe_intern(grpc_slice_from_static_string("b"), intern_values)));
+  GRPC_MDELEM_UNREF(
+      &exec_ctx,
+      b = grpc_mdelem_from_slices(
+          &exec_ctx,
+          maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+          maybe_intern(grpc_slice_from_static_string("b"), intern_values)));
+  GRPC_MDELEM_UNREF(
+      &exec_ctx,
+      c = grpc_mdelem_from_slices(
+          &exec_ctx,
+          maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+          maybe_intern(grpc_slice_from_static_string("b"), intern_values)));
+  if (intern_keys && intern_values) {
+    GPR_ASSERT(a.payload == b.payload);
+    GPR_ASSERT(a.payload == c.payload);
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_shutdown();
+}
+
+static void test_identity_laws(bool intern_keys, bool intern_values) {
+  gpr_log(GPR_INFO, "test_identity_laws: intern_keys=%d intern_values=%d",
+          intern_keys, intern_values);
+
+  grpc_init();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem a, b, c;
+  a = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  b = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  c = grpc_mdelem_from_slices(
+      &exec_ctx, maybe_intern(grpc_slice_from_static_string("a"), intern_keys),
+      maybe_intern(grpc_slice_from_static_string("b"), intern_values));
+  GPR_ASSERT(grpc_mdelem_eq(a, a));
+  GPR_ASSERT(grpc_mdelem_eq(b, b));
+  GPR_ASSERT(grpc_mdelem_eq(c, c));
+  GPR_ASSERT(grpc_mdelem_eq(a, b));
+  GPR_ASSERT(grpc_mdelem_eq(b, c));
+  GPR_ASSERT(grpc_mdelem_eq(a, c));
+  GPR_ASSERT(grpc_mdelem_eq(b, a));
+  GPR_ASSERT(grpc_mdelem_eq(c, b));
+  GPR_ASSERT(grpc_mdelem_eq(c, a));
+  if (intern_keys && intern_values) {
+    GPR_ASSERT(a.payload == b.payload);
+    GPR_ASSERT(a.payload == c.payload);
+  } else {
+    GPR_ASSERT(a.payload != b.payload);
+    GPR_ASSERT(a.payload != c.payload);
+    GPR_ASSERT(b.payload != c.payload);
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, a);
+  GRPC_MDELEM_UNREF(&exec_ctx, b);
+  GRPC_MDELEM_UNREF(&exec_ctx, c);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
 }
@@ -169,25 +241,25 @@
   size_t i, j;
   char *buffer;
   size_t nstrs = 1000;
-  grpc_mdstr **strs = gpr_malloc(sizeof(grpc_mdstr *) * nstrs);
+  grpc_slice *strs = gpr_malloc(sizeof(grpc_slice) * nstrs);
   size_t *shuf = gpr_malloc(sizeof(size_t) * nstrs);
-  grpc_mdstr *test;
+  grpc_slice test;
 
-  LOG_TEST("test_things_stick_around");
+  gpr_log(GPR_INFO, "test_things_stick_around");
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   for (i = 0; i < nstrs; i++) {
     gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x", i);
-    strs[i] = grpc_mdstr_from_string(buffer);
+    strs[i] = grpc_slice_intern(grpc_slice_from_static_string(buffer));
     shuf[i] = i;
     gpr_free(buffer);
   }
 
   for (i = 0; i < nstrs; i++) {
-    GRPC_MDSTR_REF(strs[i]);
-    GRPC_MDSTR_UNREF(&exec_ctx, strs[i]);
+    grpc_slice_ref_internal(strs[i]);
+    grpc_slice_unref_internal(&exec_ctx, strs[i]);
   }
 
   for (i = 0; i < nstrs; i++) {
@@ -199,13 +271,13 @@
   }
 
   for (i = 0; i < nstrs; i++) {
-    GRPC_MDSTR_UNREF(&exec_ctx, strs[shuf[i]]);
+    grpc_slice_unref_internal(&exec_ctx, strs[shuf[i]]);
     for (j = i + 1; j < nstrs; j++) {
       gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%" PRIuPTR "x",
                    shuf[j]);
-      test = grpc_mdstr_from_string(buffer);
-      GPR_ASSERT(test == strs[shuf[j]]);
-      GRPC_MDSTR_UNREF(&exec_ctx, test);
+      test = grpc_slice_intern(grpc_slice_from_static_string(buffer));
+      GPR_ASSERT(grpc_slice_is_equivalent(test, strs[shuf[j]]));
+      grpc_slice_unref_internal(&exec_ctx, test);
       gpr_free(buffer);
     }
   }
@@ -216,57 +288,11 @@
   gpr_free(shuf);
 }
 
-static void test_slices_work(void) {
-  /* ensure no memory leaks when switching representation from mdstr to slice */
-  grpc_mdstr *str;
-  grpc_slice slice;
-
-  LOG_TEST("test_slices_work");
-
-  grpc_init();
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  str = grpc_mdstr_from_string(
-      "123456789012345678901234567890123456789012345678901234567890");
-  slice = grpc_slice_ref(str->slice);
-  GRPC_MDSTR_UNREF(&exec_ctx, str);
-  grpc_slice_unref_internal(&exec_ctx, slice);
-
-  str = grpc_mdstr_from_string(
-      "123456789012345678901234567890123456789012345678901234567890");
-  slice = grpc_slice_ref(str->slice);
-  grpc_slice_unref_internal(&exec_ctx, slice);
-  GRPC_MDSTR_UNREF(&exec_ctx, str);
-
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
-}
-
-static void test_base64_and_huffman_works(void) {
-  grpc_mdstr *str;
-  grpc_slice slice1;
-  grpc_slice slice2;
-
-  LOG_TEST("test_base64_and_huffman_works");
-
-  grpc_init();
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  str = grpc_mdstr_from_string("abcdefg");
-  slice1 = grpc_mdstr_as_base64_encoded_and_huffman_compressed(str);
-  slice2 = grpc_chttp2_base64_encode_and_huffman_compress(str->slice);
-  GPR_ASSERT(0 == grpc_slice_cmp(slice1, slice2));
-
-  grpc_slice_unref_internal(&exec_ctx, slice2);
-  GRPC_MDSTR_UNREF(&exec_ctx, str);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_shutdown();
-}
-
 static void test_user_data_works(void) {
   int *ud1;
   int *ud2;
-  grpc_mdelem *md;
-  LOG_TEST("test_user_data_works");
+  grpc_mdelem md;
+  gpr_log(GPR_INFO, "test_user_data_works");
 
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -274,7 +300,9 @@
   *ud1 = 1;
   ud2 = gpr_malloc(sizeof(int));
   *ud2 = 2;
-  md = grpc_mdelem_from_strings(&exec_ctx, "abc", "123");
+  md = grpc_mdelem_from_slices(
+      &exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")),
+      grpc_slice_intern(grpc_slice_from_static_string("123")));
   grpc_mdelem_set_user_data(md, gpr_free, ud1);
   grpc_mdelem_set_user_data(md, gpr_free, ud2);
   GPR_ASSERT(grpc_mdelem_get_user_data(md, gpr_free) == ud1);
@@ -284,8 +312,11 @@
 }
 
 static void verify_ascii_header_size(grpc_exec_ctx *exec_ctx, const char *key,
-                                     const char *value) {
-  grpc_mdelem *elem = grpc_mdelem_from_strings(exec_ctx, key, value);
+                                     const char *value, bool intern_key,
+                                     bool intern_value) {
+  grpc_mdelem elem = grpc_mdelem_from_slices(
+      exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key),
+      maybe_intern(grpc_slice_from_static_string(value), intern_value));
   size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
   size_t expected_size = 32 + strlen(key) + strlen(value);
   GPR_ASSERT(expected_size == elem_size);
@@ -293,10 +324,13 @@
 }
 
 static void verify_binary_header_size(grpc_exec_ctx *exec_ctx, const char *key,
-                                      const uint8_t *value, size_t value_len) {
-  grpc_mdelem *elem =
-      grpc_mdelem_from_string_and_buffer(exec_ctx, key, value, value_len);
-  GPR_ASSERT(grpc_is_binary_header(key, strlen(key)));
+                                      const uint8_t *value, size_t value_len,
+                                      bool intern_key, bool intern_value) {
+  grpc_mdelem elem = grpc_mdelem_from_slices(
+      exec_ctx, maybe_intern(grpc_slice_from_static_string(key), intern_key),
+      maybe_intern(grpc_slice_from_static_buffer(value, value_len),
+                   intern_value));
+  GPR_ASSERT(grpc_is_binary_header(GRPC_MDKEY(elem)));
   size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
   grpc_slice value_slice =
       grpc_slice_from_copied_buffer((const char *)value, value_len);
@@ -309,8 +343,9 @@
 }
 
 #define BUFFER_SIZE 64
-static void test_mdelem_sizes_in_hpack(void) {
-  LOG_TEST("test_mdelem_size");
+static void test_mdelem_sizes_in_hpack(bool intern_key, bool intern_value) {
+  gpr_log(GPR_INFO, "test_mdelem_size: intern_key=%d intern_value=%d",
+          intern_key, intern_value);
   grpc_init();
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
@@ -319,19 +354,44 @@
     binary_value[i] = i;
   }
 
-  verify_ascii_header_size(&exec_ctx, "hello", "world");
+  verify_ascii_header_size(&exec_ctx, "hello", "world", intern_key,
+                           intern_value);
   verify_ascii_header_size(&exec_ctx, "hello",
-                           "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
-  verify_ascii_header_size(&exec_ctx, ":scheme", "http");
+                           "worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", intern_key,
+                           intern_value);
+  verify_ascii_header_size(&exec_ctx, ":scheme", "http", intern_key,
+                           intern_value);
 
   for (uint8_t i = 0; i < BUFFER_SIZE; i++) {
-    verify_binary_header_size(&exec_ctx, "hello-bin", binary_value, i);
+    verify_binary_header_size(&exec_ctx, "hello-bin", binary_value, i,
+                              intern_key, intern_value);
   }
 
-  const char *static_metadata = grpc_static_metadata_strings[0];
-  memcpy(binary_value, static_metadata, strlen(static_metadata));
-  verify_binary_header_size(&exec_ctx, "hello-bin", binary_value,
-                            strlen(static_metadata));
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_shutdown();
+}
+
+static void test_copied_static_metadata(bool dup_key, bool dup_value) {
+  gpr_log(GPR_INFO, "test_static_metadata: dup_key=%d dup_value=%d", dup_key,
+          dup_value);
+  grpc_init();
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; i++) {
+    grpc_mdelem p = GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[i],
+                                     GRPC_MDELEM_STORAGE_STATIC);
+    grpc_mdelem q =
+        grpc_mdelem_from_slices(&exec_ctx, maybe_dup(GRPC_MDKEY(p), dup_key),
+                                maybe_dup(GRPC_MDVALUE(p), dup_value));
+    GPR_ASSERT(grpc_mdelem_eq(p, q));
+    if (dup_key || dup_value) {
+      GPR_ASSERT(p.payload != q.payload);
+    } else {
+      GPR_ASSERT(p.payload == q.payload);
+    }
+    GRPC_MDELEM_UNREF(&exec_ctx, p);
+    GRPC_MDELEM_UNREF(&exec_ctx, q);
+  }
 
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
@@ -340,15 +400,18 @@
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_no_op();
-  test_create_string();
-  test_create_metadata();
-  test_create_many_ephemeral_metadata();
+  for (int k = 0; k <= 1; k++) {
+    for (int v = 0; v <= 1; v++) {
+      test_create_metadata(k, v);
+      test_create_many_ephemeral_metadata(k, v);
+      test_identity_laws(k, v);
+      test_spin_creating_the_same_thing(k, v);
+      test_mdelem_sizes_in_hpack(k, v);
+      test_copied_static_metadata(k, v);
+    }
+  }
   test_create_many_persistant_metadata();
-  test_spin_creating_the_same_thing();
   test_things_stick_around();
-  test_slices_work();
-  test_base64_and_huffman_works();
   test_user_data_works();
-  test_mdelem_sizes_in_hpack();
   return 0;
 }
diff --git a/test/core/transport/chttp2/status_conversion_test.c b/test/core/transport/status_conversion_test.c
similarity index 65%
rename from test/core/transport/chttp2/status_conversion_test.c
rename to test/core/transport/status_conversion_test.c
index f5a5cd1..65f840b 100644
--- a/test/core/transport/chttp2/status_conversion_test.c
+++ b/test/core/transport/status_conversion_test.c
@@ -31,50 +31,50 @@
  *
  */
 
-#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
+#include "src/core/lib/transport/status_conversion.h"
 #include <grpc/support/log.h>
 #include "test/core/util/test_config.h"
 
 #define GRPC_STATUS_TO_HTTP2_ERROR(a, b) \
-  GPR_ASSERT(grpc_chttp2_grpc_status_to_http2_error(a) == (b))
+  GPR_ASSERT(grpc_status_to_http2_error(a) == (b))
 #define HTTP2_ERROR_TO_GRPC_STATUS(a, deadline, b) \
-  GPR_ASSERT(grpc_chttp2_http2_error_to_grpc_status(a, deadline) == (b))
+  GPR_ASSERT(grpc_http2_error_to_grpc_status(a, deadline) == (b))
 #define GRPC_STATUS_TO_HTTP2_STATUS(a, b) \
-  GPR_ASSERT(grpc_chttp2_grpc_status_to_http2_status(a) == (b))
+  GPR_ASSERT(grpc_status_to_http2_status(a) == (b))
 #define HTTP2_STATUS_TO_GRPC_STATUS(a, b) \
-  GPR_ASSERT(grpc_chttp2_http2_status_to_grpc_status(a) == (b))
+  GPR_ASSERT(grpc_http2_status_to_grpc_status(a) == (b))
 
 int main(int argc, char **argv) {
   int i;
 
   grpc_test_init(argc, argv);
 
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OK, GRPC_CHTTP2_NO_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_CANCELLED, GRPC_CHTTP2_CANCEL);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNKNOWN, GRPC_CHTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OK, GRPC_HTTP2_NO_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_CANCELLED, GRPC_HTTP2_CANCEL);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNKNOWN, GRPC_HTTP2_INTERNAL_ERROR);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INVALID_ARGUMENT,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED, GRPC_CHTTP2_CANCEL);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_NOT_FOUND, GRPC_CHTTP2_INTERNAL_ERROR);
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DEADLINE_EXCEEDED, GRPC_HTTP2_CANCEL);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_NOT_FOUND, GRPC_HTTP2_INTERNAL_ERROR);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ALREADY_EXISTS,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
+                             GRPC_HTTP2_INTERNAL_ERROR);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_PERMISSION_DENIED,
-                             GRPC_CHTTP2_INADEQUATE_SECURITY);
+                             GRPC_HTTP2_INADEQUATE_SECURITY);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAUTHENTICATED,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
+                             GRPC_HTTP2_INTERNAL_ERROR);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_RESOURCE_EXHAUSTED,
-                             GRPC_CHTTP2_ENHANCE_YOUR_CALM);
+                             GRPC_HTTP2_ENHANCE_YOUR_CALM);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_FAILED_PRECONDITION,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ABORTED, GRPC_CHTTP2_INTERNAL_ERROR);
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_ABORTED, GRPC_HTTP2_INTERNAL_ERROR);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_OUT_OF_RANGE,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
+                             GRPC_HTTP2_INTERNAL_ERROR);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNIMPLEMENTED,
-                             GRPC_CHTTP2_INTERNAL_ERROR);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INTERNAL, GRPC_CHTTP2_INTERNAL_ERROR);
+                             GRPC_HTTP2_INTERNAL_ERROR);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_INTERNAL, GRPC_HTTP2_INTERNAL_ERROR);
   GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_UNAVAILABLE,
-                             GRPC_CHTTP2_REFUSED_STREAM);
-  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DATA_LOSS, GRPC_CHTTP2_INTERNAL_ERROR);
+                             GRPC_HTTP2_REFUSED_STREAM);
+  GRPC_STATUS_TO_HTTP2_ERROR(GRPC_STATUS_DATA_LOSS, GRPC_HTTP2_INTERNAL_ERROR);
 
   GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_OK, 200);
   GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_CANCELLED, 200);
@@ -95,59 +95,59 @@
   GRPC_STATUS_TO_HTTP2_STATUS(GRPC_STATUS_DATA_LOSS, 200);
 
   const gpr_timespec before_deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_NO_ERROR, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_PROTOCOL_ERROR, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INTERNAL_ERROR, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FLOW_CONTROL_ERROR, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_SETTINGS_TIMEOUT, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_STREAM_CLOSED, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FRAME_SIZE_ERROR, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_REFUSED_STREAM, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, before_deadline,
                              GRPC_STATUS_UNAVAILABLE);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CANCEL, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, before_deadline,
                              GRPC_STATUS_CANCELLED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_COMPRESSION_ERROR, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CONNECT_ERROR, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, before_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_ENHANCE_YOUR_CALM, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, before_deadline,
                              GRPC_STATUS_RESOURCE_EXHAUSTED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INADEQUATE_SECURITY, before_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, before_deadline,
                              GRPC_STATUS_PERMISSION_DENIED);
 
   const gpr_timespec after_deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_NO_ERROR, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_NO_ERROR, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_PROTOCOL_ERROR, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_PROTOCOL_ERROR, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INTERNAL_ERROR, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INTERNAL_ERROR, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FLOW_CONTROL_ERROR, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FLOW_CONTROL_ERROR, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_SETTINGS_TIMEOUT, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_SETTINGS_TIMEOUT, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_STREAM_CLOSED, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_STREAM_CLOSED, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_FRAME_SIZE_ERROR, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_FRAME_SIZE_ERROR, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_REFUSED_STREAM, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_REFUSED_STREAM, after_deadline,
                              GRPC_STATUS_UNAVAILABLE);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CANCEL, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CANCEL, after_deadline,
                              GRPC_STATUS_DEADLINE_EXCEEDED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_COMPRESSION_ERROR, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_COMPRESSION_ERROR, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_CONNECT_ERROR, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_CONNECT_ERROR, after_deadline,
                              GRPC_STATUS_INTERNAL);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_ENHANCE_YOUR_CALM, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_ENHANCE_YOUR_CALM, after_deadline,
                              GRPC_STATUS_RESOURCE_EXHAUSTED);
-  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_CHTTP2_INADEQUATE_SECURITY, after_deadline,
+  HTTP2_ERROR_TO_GRPC_STATUS(GRPC_HTTP2_INADEQUATE_SECURITY, after_deadline,
                              GRPC_STATUS_PERMISSION_DENIED);
 
   HTTP2_STATUS_TO_GRPC_STATUS(200, GRPC_STATUS_OK);
@@ -165,7 +165,7 @@
 
   /* check all status values can be converted */
   for (i = 0; i <= 999; i++) {
-    grpc_chttp2_http2_status_to_grpc_status(i);
+    grpc_http2_status_to_grpc_status(i);
   }
 
   return 0;
diff --git a/test/core/transport/timeout_encoding_test.c b/test/core/transport/timeout_encoding_test.c
index b6004af..10e1804 100644
--- a/test/core/transport/timeout_encoding_test.c
+++ b/test/core/transport/timeout_encoding_test.c
@@ -88,7 +88,8 @@
 static void assert_decodes_as(const char *buffer, gpr_timespec expected) {
   gpr_timespec got;
   gpr_log(GPR_INFO, "check decoding '%s'", buffer);
-  GPR_ASSERT(1 == grpc_http2_decode_timeout(buffer, &got));
+  GPR_ASSERT(1 == grpc_http2_decode_timeout(
+                      grpc_slice_from_static_string(buffer), &got));
   GPR_ASSERT(0 == gpr_time_cmp(got, expected));
 }
 
@@ -134,18 +135,23 @@
   assert_decodes_as("9999999999S", gpr_inf_future(GPR_TIMESPAN));
 }
 
-void test_decoding_fails(void) {
+static void assert_decoding_fails(const char *s) {
   gpr_timespec x;
+  GPR_ASSERT(0 ==
+             grpc_http2_decode_timeout(grpc_slice_from_static_string(s), &x));
+}
+
+void test_decoding_fails(void) {
   LOG_TEST("test_decoding_fails");
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout(" ", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("x", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("1", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("1x", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("1ux", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("!", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("n1", &x));
-  GPR_ASSERT(0 == grpc_http2_decode_timeout("-1u", &x));
+  assert_decoding_fails("");
+  assert_decoding_fails(" ");
+  assert_decoding_fails("x");
+  assert_decoding_fails("1");
+  assert_decoding_fails("1x");
+  assert_decoding_fails("1ux");
+  assert_decoding_fails("!");
+  assert_decoding_fails("n1");
+  assert_decoding_fails("-1u");
 }
 
 int main(int argc, char **argv) {
diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c
index 4baf63d..118708d 100644
--- a/test/core/util/port_server_client.c
+++ b/test/core/util/port_server_client.c
@@ -152,7 +152,7 @@
     failed = 1;
     const char *msg = grpc_error_string(error);
     gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg);
-    grpc_error_free_string(msg);
+
   } else if (response->status != 200) {
     failed = 1;
     gpr_log(GPR_DEBUG, "failed port pick from server: status=%d",