You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by br...@apache.org on 2014/05/20 00:33:55 UTC
git commit: Adding unit test for HdrHeap coalesce crash (TS-2766)
Repository: trafficserver
Updated Branches:
refs/heads/master 05f4db0d9 -> 1fec97e14
Adding unit test for HdrHeap coalesce crash (TS-2766)
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/1fec97e1
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/1fec97e1
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/1fec97e1
Branch: refs/heads/master
Commit: 1fec97e14491d9ecd2f90063ceeaea8dcea97a8e
Parents: 05f4db0
Author: Brian Geffon <br...@apache.org>
Authored: Mon May 19 15:33:37 2014 -0700
Committer: Brian Geffon <br...@apache.org>
Committed: Mon May 19 15:33:37 2014 -0700
----------------------------------------------------------------------
proxy/hdrs/HdrHeap.cc | 124 +++++++++++++++++++++++++++------------------
1 file changed, 76 insertions(+), 48 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1fec97e1/proxy/hdrs/HdrHeap.cc
----------------------------------------------------------------------
diff --git a/proxy/hdrs/HdrHeap.cc b/proxy/hdrs/HdrHeap.cc
index 296f766..cd762e6 100644
--- a/proxy/hdrs/HdrHeap.cc
+++ b/proxy/hdrs/HdrHeap.cc
@@ -1198,68 +1198,96 @@ struct StrTest
int len;
};
-#ifdef TESTS
-static void
-hdr_heap_test_verify(StrTest * str_test, int n)
-{
- for (int i = 0; i < n; i++) {
- char *ptr = str_test[i].ptr;
- int len = str_test[i].len;
-
- char c = (char) (len % 43);
- for (int m = 0; m < len; m++) {
- if (ptr[m] != c) {
- Warning("Str Test failed on str %d of %d", i, n);
- return;
- }
- c++;
- }
+#if TS_HAS_TESTS
+#include <ts/TestBox.h>
+REGRESSION_TEST(HdrHeap_Coalesce)(RegressionTest* t, int /* atype ATS_UNUSED */, int* pstatus) {
+ *pstatus = REGRESSION_TEST_PASSED;
+ /*
+ * This test is designed to test numerous pieces of the HdrHeaps including allocations,
+ * demotion of rw heaps to ronly heaps, and finally the coalesce and evacuate behaviours.
+ */
+
+ // The amount of space we will need to overflow the StrHdrHeap is HDR_STR_HEAP_DEFAULT_SIZE - STR_HEAP_HDR_SIZE
+ size_t next_rw_heap_size = HDR_STR_HEAP_DEFAULT_SIZE;
+ size_t next_required_overflow_size = next_rw_heap_size - STR_HEAP_HDR_SIZE;
+ char buf[next_required_overflow_size];
+ for(unsigned int i = 0; i < sizeof(buf); ++i) {
+ buf[i] = ('a' + (i % 26));
}
-}
+ TestBox tb(t, pstatus);
+ HdrHeap *heap = new_HdrHeap();
+ URLImpl *url = url_create(heap);
-// NOTE: the tests are current broken since
-// they don't have objects that can
-// string evacuation
-void
-hdr_heap_test()
-{
- Note("Starting hdr heap test");
+ tb.check(heap->m_read_write_heap.m_ptr == NULL, "Checking that we have no rw heap.");
+ url_path_set(heap,url, buf, next_required_overflow_size, true);
+ tb.check(heap->m_read_write_heap->m_free_size == 0, "Checking that we've completely consumed the rw heap");
+ for (int i = 0; i < HDR_BUF_RONLY_HEAPS; ++i) {
+ tb.check(heap->m_ronly_heap[i].m_heap_start == (char*)NULL, "Checking ronly_heap[%d] is NULL", i);
+ }
+
+ // Now we have no ronly heaps in use and a completely full rwheap, so we will test that
+ // we demote to ronly heaps HDR_BUF_RONLY_HEAPS times.
+ for (int ronly_heap = 0; ronly_heap < HDR_BUF_RONLY_HEAPS; ++ronly_heap) {
+ next_rw_heap_size = 2 * heap->m_read_write_heap->m_heap_size;
+ next_required_overflow_size = next_rw_heap_size - STR_HEAP_HDR_SIZE;
+ char buf2[next_required_overflow_size];
+ for(unsigned int i = 0; i < sizeof(buf2); ++i) {
+ buf2[i] = ('a' + (i % 26));
+ }
- HdrHeap *h = new_HdrHeap();
+ URLImpl *url2 = url_create(heap);
+ url_path_set(heap,url2,buf2,next_required_overflow_size, true);
- int s;
- for (int i = 0; i < 10; i++) {
- s = 16;
- while (s < HDR_MAX_ALLOC_SIZE) {
- h->allocate_obj(s);
- s++;
+ tb.check(heap->m_read_write_heap->m_heap_size == (uint32_t)next_rw_heap_size, "Checking the current rw heap is %d bytes", next_rw_heap_size);
+ tb.check(heap->m_read_write_heap->m_free_size == 0, "Checking that we've completely consumed the rw heap");
+ tb.check(heap->m_ronly_heap[ronly_heap].m_heap_start != NULL, "Checking that we properly demoted the previous rw heap");
+ for (int i = ronly_heap + 1; i < HDR_BUF_RONLY_HEAPS; ++i) {
+ tb.check(heap->m_ronly_heap[i].m_heap_start == NULL, "Checking ronly_heap[%d] is NULL", i);
}
}
+ // We will rerun these checks after we introduce a non-copied string to make sure we didn't already coalesce
+ for (int i = 0; i < HDR_BUF_RONLY_HEAPS; ++i) {
+ tb.check(heap->m_ronly_heap[i].m_heap_start != (char*)NULL, "Pre non-copied string: Checking ronly_heap[%d] is NOT NULL", i);
+ }
- // Allocate a bunch of strings
- StrTest str_test[10000];
- s = 16;
- for (int j = 0; j < 10000; j++) {
- str_test[j].ptr = h->allocate_str(s);
- str_test[j].len = s;
+ // Now if we add a url object that contains only non-copied strings it shouldn't affect the size of the rwheap
+ // since it doesn't require allocating any storage on this heap.
+ char buf3[next_required_overflow_size];
+ for(unsigned int i = 0; i < sizeof(buf); ++i) {
+ buf3[i] = ('a' + (i % 26));
+ }
- char c = (char) (s % 43);
- for (int k = 0; k < s; k++) {
- str_test[j].ptr[k] = c;
- c++;
- }
+ URLImpl *aliased_str_url = url_create(heap);
+ url_path_set(heap, aliased_str_url, buf3, next_required_overflow_size, false); // don't copy this string
+ tb.check(aliased_str_url->m_len_path == next_required_overflow_size, "Checking that the aliased string shows having proper length");
+ tb.check(aliased_str_url->m_ptr_path == buf3, "Checking that the aliased string is correctly pointing at buf");
- hdr_heap_test_verify(str_test, j + 1);
- s += 1;
+
+ for (int i = 0; i < HDR_BUF_RONLY_HEAPS; ++i) {
+ tb.check(heap->m_ronly_heap[i].m_heap_start != (char*)NULL, "Post non-copied string: Checking ronly_heap[%d] is NOT NULL", i);
}
+ tb.check(heap->m_read_write_heap->m_free_size == 0, "Checking that we've completely consumed the rw heap");
+ tb.check(heap->m_next == NULL, "Checking that we dont have any chained heaps");
+ // Now at this point we have a completely full rw_heap and no ronly heap slots, so any allocation would have to result
+ // in a coalesce, and to validate that we don't reintroduce TS-2766 we have an aliased string, so when it tries to
+ // coalesce it used to sum up the size of the ronly heaps and the rw heap which is incorrect because we never
+ // copied the above string onto the heap. The new behaviour fixed in TS-2766 will make sure that this non copied
+ // string is accounted for, in the old implementation it would result in an allocation failure.
- // Make sure the strings are all intact
- hdr_heap_test_verify(str_test, 100);
- Note("Str Test completed");
-}
+ char *str = heap->allocate_str(1); // this will force a coalese.
+ tb.check(str != NULL, "Checking that 1 byte allocated string is not NULL");
+ // Now we need to validate that aliased_str_url has a path that isn't NULL, if it's NULL then the
+ // coalesce is broken and didn't properly determine the size, if it's not null then everything worked as expected.
+ tb.check(aliased_str_url->m_len_path == next_required_overflow_size, "Checking that the aliased string shows having proper length");
+ tb.check(aliased_str_url->m_ptr_path != NULL, "Checking that the aliased string was properly moved during coalsece and evacuation");
+ tb.check(aliased_str_url->m_ptr_path != buf3, "Checking that the aliased string was properly moved during coalsece and evacuation (not pointing at buf3)");
+
+ // Clean up
+ heap->destroy();
+}
#endif