IPv6 map problem replicated.
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/fcd092c5 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/fcd092c5 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/fcd092c5 Branch: refs/heads/master Commit: fcd092c5860639e1edf858f8c8b0727999eff7c6 Parents: 5b20a22 Author: Alan M. Carroll <[email protected]> Authored: Mon Mar 19 19:22:00 2012 -0500 Committer: Alan M. Carroll <[email protected]> Committed: Mon Mar 19 19:22:00 2012 -0500 ---------------------------------------------------------------------- lib/ts/IntrusivePtrTest.cc | 75 ++++++++++++++++++++++ lib/ts/IpMapTest.cc | 130 ++++++++++++++++++++------------------- lib/ts/TestBox.h | 63 +++++++++++++++++++ 3 files changed, 205 insertions(+), 63 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fcd092c5/lib/ts/IntrusivePtrTest.cc ---------------------------------------------------------------------- diff --git a/lib/ts/IntrusivePtrTest.cc b/lib/ts/IntrusivePtrTest.cc new file mode 100644 index 0000000..d58db69 --- /dev/null +++ b/lib/ts/IntrusivePtrTest.cc @@ -0,0 +1,75 @@ +/** @file + + Intrusive pointer test. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +# include <ts/IntrusivePtr.h> +# include <ts/IntrusiveDList.h> +# include <ts/TestBox.h> + +namespace { // Hide our local defintions + +// Test class for pointers and lists. +class A : public IntrusivePtrCounter { +public: + A() : _data(0) {} + static A*& nextPtr(A* a) { return a->_next; } + static A*& prevPtr(A* a) { return a->_prev; } + int _data; + A* _next; + A* _prev; +}; + +// Definitions to test compilation. +typedef IntrusivePtrQueue< + A, + IntrusivePtrLinkFunction<A, &A::nextPtr, &A::prevPtr> +> AList; + +} + +REGRESSION_TEST(IntrusivePtr_Test_Basic)(RegressionTest* t, int atype, int* pstatus) { + IntrusivePtr<A> ptr1; + IntrusivePtr<A> ptr2(new A); + + TestBox tb(t, pstatus); + + tb = REGRESSION_TEST_PASSED; + + tb.check(!ptr1, "Default construct pointer is not empty."); + tb.check(ptr2, "Construction from pointer was empty."); + + AList alist1; + + tb.check(ptr2->useCount() == 1, "Bad use count: expected 1 got %d", ptr2->useCount()); + alist1.append(ptr2); + tb.check(ptr2->useCount() == 2, "Bad use count: expected 2 got %d", ptr2->useCount()); + alist1.remove(ptr2); + tb.check(ptr2->useCount() == 1, "Bad use count: expected 1 got %d", ptr2->useCount()); + alist1.prepend(ptr2); + tb.check(ptr2->useCount() == 2, "Bad use count: expected 2 got %d", ptr2->useCount()); + for ( AList::iterator spot = alist1.begin(), limit = alist1.end() + ; spot != limit + ; ++spot + ) { + if (spot->_data) break; + } +} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fcd092c5/lib/ts/IpMapTest.cc ---------------------------------------------------------------------- diff --git a/lib/ts/IpMapTest.cc b/lib/ts/IpMapTest.cc index 5e00b5a..34a0bfb 100644 --- a/lib/ts/IpMapTest.cc +++ b/lib/ts/IpMapTest.cc @@ -21,23 +21,8 @@ limitations under the License. */ -# include "IpMap.h" -# include "Regression.h" - -inline bool check(RegressionTest* t, int* pstatus, bool test, char const* fmt, ...) { - if (!test) { - static size_t const N = 1<<16; - char buffer[N]; // just stack, go big. - va_list ap; - va_start(ap, fmt); - vsnprintf(buffer, N, fmt, ap); - va_end(ap); - rprintf(t, "%s\n", buffer); - *pstatus = REGRESSION_TEST_FAILED; - } - return test; -} - +#include <ts/IpMap.h> +#include <ts/TestBox.h> void IpMapTestPrint(IpMap& map) { @@ -54,6 +39,8 @@ IpMapTestPrint(IpMap& map) { } REGRESSION_TEST(IpMap_Basic)(RegressionTest* t, int atype, int* pstatus) { + TestBox tb(t, pstatus); + IpMap map; void* const markA = reinterpret_cast<void*>(1); void* const markB = reinterpret_cast<void*>(2); @@ -73,52 +60,53 @@ REGRESSION_TEST(IpMap_Basic)(RegressionTest* t, int atype, int* pstatus) { map.mark(ip10,ip20,markA); map.mark(ip5, ip9, markA); - check(t, pstatus, map.getCount() == 1, "Coalesce failed"); - check(t, pstatus, map.contains(ip9), "Range max not found."); - check(t, pstatus, map.contains(ip10, &mark), "Span min not found."); - check(t, pstatus, mark == markA, "Mark not preserved."); + tb.check(map.getCount() == 1, "Coalesce failed"); + tb.check(map.contains(ip9), "Range max not found."); + tb.check(map.contains(ip10, &mark), "Span min not found."); + tb.check(mark == markA, "Mark not preserved."); map.fill(ip15, ip100, markB); - check(t, pstatus, map.getCount() == 2, "Fill failed."); - check(t, pstatus, map.contains(ip50, &mark), "Fill interior missing."); - check(t, pstatus, mark == markB, "Fill mark not preserved."); - check(t, pstatus, !map.contains(ip200), "Span min not found."); - check(t, pstatus, map.contains(ip15, &mark), "Old span interior not found."); - check(t, pstatus, mark == markA, "Fill overwrote mark."); + tb.check(map.getCount() == 2, "Fill failed."); + tb.check(map.contains(ip50, &mark), "Fill interior missing."); + tb.check(mark == markB, "Fill mark not preserved."); + tb.check(!map.contains(ip200), "Span min not found."); + tb.check(map.contains(ip15, &mark), "Old span interior not found."); + tb.check(mark == markA, "Fill overwrote mark."); map.clear(); - check(t, pstatus, map.getCount() == 0, "Clear failed."); + tb.check(map.getCount() == 0, "Clear failed."); map.mark(ip20, ip50, markA); map.mark(ip100, ip150, markB); map.fill(ip10, ip200, markC); - check(t, pstatus, map.getCount() == 5, "Test 3 failed [expected 5, got %d].", map.getCount()); - check(t, pstatus, map.contains(ip15, &mark), "Test 3 - left span missing."); - check(t, pstatus, map.contains(ip60, &mark), "Test 3 - middle span missing."); - check(t, pstatus, mark == markC, "Test 3 - fill mark wrong."); - check(t, pstatus, map.contains(ip160), "Test 3 - right span missing."); - check(t, pstatus, map.contains(ip120, &mark), "Test 3 - right mark span missing."); - check(t, pstatus, mark == markB, "Test 3 - wrong data on right mark span."); + tb.check(map.getCount() == 5, "Test 3 failed [expected 5, got %d].", map.getCount()); + tb.check(map.contains(ip15, &mark), "Test 3 - left span missing."); + tb.check(map.contains(ip60, &mark), "Test 3 - middle span missing."); + tb.check(mark == markC, "Test 3 - fill mark wrong."); + tb.check(map.contains(ip160), "Test 3 - right span missing."); + tb.check(map.contains(ip120, &mark), "Test 3 - right mark span missing."); + tb.check(mark == markB, "Test 3 - wrong data on right mark span."); map.unmark(ip140, ip160); - check(t, pstatus, map.getCount() == 5, "Test 3 unmark failed [expected 5, got %d].", map.getCount()); - check(t, pstatus, !map.contains(ip140), "Test 3 - unmark left edge still there."); - check(t, pstatus, !map.contains(ip150), "Test 3 - unmark middle still there."); - check(t, pstatus, !map.contains(ip160), "Test 3 - unmark right edge still there."); + tb.check(map.getCount() == 5, "Test 3 unmark failed [expected 5, got %d].", map.getCount()); + tb.check(!map.contains(ip140), "Test 3 - unmark left edge still there."); + tb.check(!map.contains(ip150), "Test 3 - unmark middle still there."); + tb.check(!map.contains(ip160), "Test 3 - unmark right edge still there."); map.clear(); map.mark(ip20,ip20, markA); - check(t, pstatus, map.contains(ip20), "Map failed on singleton insert"); + tb.check(map.contains(ip20), "Map failed on singleton insert"); map.mark(ip10, ip200, markB); mark=0; map.contains(ip20, &mark); - check(t, pstatus, mark == markB, "Map held singleton against range."); + tb.check(mark == markB, "Map held singleton against range."); map.mark(ip100, ip120, markA); map.mark(ip150, ip160, markB); map.mark(ip0, ipmax, markC); - check(t, pstatus, map.getCount() == 1, "IpMap: Full range fill left extra ranges."); + tb.check(map.getCount() == 1, "IpMap: Full range fill left extra ranges."); } REGRESSION_TEST(IpMap_Unmark)(RegressionTest* t, int atype, int* pstatus) { + TestBox tb(t, pstatus); IpMap map; // ip_text_buffer ipb1, ipb2; void* const markA = reinterpret_cast<void*>(1); @@ -150,23 +138,24 @@ REGRESSION_TEST(IpMap_Unmark)(RegressionTest* t, int atype, int* pstatus) { *pstatus = REGRESSION_TEST_PASSED; map.mark(&a_0, &a_max, markA); - check(t, pstatus, map.getCount() == 1, "IpMap Unmark: Full range not single."); + tb.check(map.getCount() == 1, "IpMap Unmark: Full range not single."); map.unmark(&a_10_28_56_0, &a_10_28_56_255); - check(t, pstatus, map.getCount() == 2, "IpMap Unmark: Range unmark failed."); + tb.check(map.getCount() == 2, "IpMap Unmark: Range unmark failed."); // Generic range check. - check(t, pstatus, !map.contains(&a_10_28_56_0), "IpMap Unmark: Range unmark min address not removed."); - check(t, pstatus, !map.contains(&a_10_28_56_255), "IpMap Unmark: Range unmark max address not removed."); - check(t, pstatus, map.contains(&a_10_28_55_255), "IpMap Unmark: Range unmark min-1 address removed."); - check(t, pstatus, map.contains(&a_10_28_57_0), "IpMap Unmark: Range unmark max+1 address removed."); + tb.check(!map.contains(&a_10_28_56_0), "IpMap Unmark: Range unmark min address not removed."); + tb.check(!map.contains(&a_10_28_56_255), "IpMap Unmark: Range unmark max address not removed."); + tb.check(map.contains(&a_10_28_55_255), "IpMap Unmark: Range unmark min-1 address removed."); + tb.check(map.contains(&a_10_28_57_0), "IpMap Unmark: Range unmark max+1 address removed."); // Test min bounded range. map.unmark(&a_0, &a_0_0_0_16); - check(t, pstatus, !map.contains(&a_0), "IpMap Unmark: Range unmark zero address not removed."); - check(t, pstatus, !map.contains(&a_0_0_0_16), "IpMap Unmark: Range unmark zero bounded range max not removed."); - check(t, pstatus, map.contains(&a_0_0_0_17), "IpMap Unmark: Range unmark zero bounded range max+1 removed."); + tb.check(!map.contains(&a_0), "IpMap Unmark: Range unmark zero address not removed."); + tb.check(!map.contains(&a_0_0_0_16), "IpMap Unmark: Range unmark zero bounded range max not removed."); + tb.check(map.contains(&a_0_0_0_17), "IpMap Unmark: Range unmark zero bounded range max+1 removed."); IpMapTestPrint(map); } REGRESSION_TEST(IpMap_Fill)(RegressionTest* t, int atype, int* pstatus) { + TestBox tb(t, pstatus); IpMap map; ip_text_buffer ipb1, ipb2; void* const allow = reinterpret_cast<void*>(0); @@ -213,36 +202,51 @@ REGRESSION_TEST(IpMap_Fill)(RegressionTest* t, int atype, int* pstatus) { map.fill(&a_10_28_56_0,&a_10_28_56_255,deny); map.fill(&a0,&a_max,allow); - check(t, pstatus, map.contains(&a_10_28_56_4,&mark), "IpMap Fill: Target not found."); - check(t, pstatus, mark == deny, "IpMap Fill: Expected deny, got allow at %s.", ats_ip_ntop(&a_10_28_56_4, ipb1, sizeof(ipb1))); + tb.check(map.contains(&a_10_28_56_4,&mark), "IpMap Fill: Target not found."); + tb.check(mark == deny, "IpMap Fill: Expected deny, got allow at %s.", ats_ip_ntop(&a_10_28_56_4, ipb1, sizeof(ipb1))); map.clear(); map.fill(&a_loopback, &a_loopback, allow); - check(t, pstatus, map.contains(&a_loopback), "IpMap fill: singleton not marked."); + tb.check(map.contains(&a_loopback), "IpMap fill: singleton not marked."); map.fill(&a0, &a_max, deny); mark=0; - check(t, pstatus, map.contains(&a_loopback, &mark), "IpMap fill: singleton marking lost."); - check(t, pstatus, mark == allow, "IpMap fill: overwrote existing singleton mark."); - if (check(t, pstatus, map.begin() != map.end(), "IpMap fill: map is empty.")) { - if (check(t, pstatus, ++(map.begin()) != map.end(), "IpMap fill: only one range.")) { - check(t, pstatus, -1 == ats_ip_addr_cmp(map.begin()->max(), (++map.begin())->min()), "IpMap fill: ranges not disjoint [%s < %s].", ats_ip_ntop(map.begin()->max(), ipb1, sizeof(ipb1)), ats_ip_ntop((++map.begin())->min(), ipb2, sizeof(ipb2))); + tb.check(map.contains(&a_loopback, &mark), "IpMap fill: singleton marking lost."); + tb.check(mark == allow, "IpMap fill: overwrote existing singleton mark."); + if (tb.check(map.begin() != map.end(), "IpMap fill: map is empty.")) { + if (tb.check(++(map.begin()) != map.end(), "IpMap fill: only one range.")) { + tb.check(-1 == ats_ip_addr_cmp(map.begin()->max(), (++map.begin())->min()), "IpMap fill: ranges not disjoint [%s < %s].", ats_ip_ntop(map.begin()->max(), ipb1, sizeof(ipb1)), ats_ip_ntop((++map.begin())->min(), ipb2, sizeof(ipb2))); } } map.clear(); map.fill(&a_loopback, &a_loopback2, markA); map.fill(&a_10_28_56_0, &a_10_28_56_255, markB); - check(t, pstatus, !map.contains(&a_63_128_1_12, &mark), "IpMap fill[2]: over extended range."); + tb.check(!map.contains(&a_63_128_1_12, &mark), "IpMap fill[2]: over extended range."); map.fill(&a0, &a_max, deny); - check(t, pstatus, map.getCount() == 5, "IpMap[2]: Fill failed."); - if (check(t, pstatus, map.contains(&a_63_128_1_12, &mark), "IpMap fill[2]: missing mark")) { - check(t, pstatus, mark == deny, "IpMap fill[2]: missing range"); + tb.check(map.getCount() == 5, "IpMap[2]: Fill failed."); + if (tb.check(map.contains(&a_63_128_1_12, &mark), "IpMap fill[2]: missing mark")) { + tb.check(mark == deny, "IpMap fill[2]: missing range"); } map.fill(&a_fe80_9d90, &a_fe80_9d9d, markA); map.fill(&a_0000_0001, &a_0000_0001, markA); map.fill(&a_0000_0000, &a_ffff_ffff, markB); + + tb.check(map.contains(&a_0000_0000, &mark) && mark == markB, + "IpMap Fill[v6]: Zero address has bad mark."); + tb.check(map.contains(&a_ffff_ffff, &mark) && mark == markB, + "IpMap Fill[v6]: Max address has bad mark."); + tb.check(map.contains(&a_fe80_9d90, &mark) && mark == markA, + "IpMap Fill[v6]: 9d90 address has bad mark."); + tb.check(map.contains(&a_fe80_9d89, &mark) && mark == markB, + "IpMap Fill[v6]: 9d89 address has bad mark."); + tb.check(map.contains(&a_fe80_9d9d, &mark) && mark == markA, + "IpMap Fill[v6]: 9d9d address has bad mark."); + tb.check(map.contains(&a_fe80_9d9e, &mark) && mark == markB, + "IpMap Fill[v6]: 9d9b address has bad mark."); + tb.check(map.contains(&a_0000_0001, &mark) && mark == markA, + "IpMap Fill[v6]: ::1 has bad mark."); IpMapTestPrint(map); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fcd092c5/lib/ts/TestBox.h ---------------------------------------------------------------------- diff --git a/lib/ts/TestBox.h b/lib/ts/TestBox.h new file mode 100644 index 0000000..df31a6e --- /dev/null +++ b/lib/ts/TestBox.h @@ -0,0 +1,63 @@ +#if ! defined(TS_TEST_BOX_HEADER) +#define TS_TEST_BOX_HEADER + +/** @file + + Regression testing support class. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +# include <ts/Regression.h> + +namespace { + /** Class to make handling regression tests easier. + This holds the important regression test values so they don't have to + be passed repeated. + */ + struct TestBox { + typedef TestBox self; ///< Self reference type. + RegressionTest* _test; ///< The test object. + int* _status; ///< Current status pointer. + + /// Construct from @a test object and @a status pointer. + TestBox(RegressionTest* test, int* status) : _test(test), _status(status) {} + /// Check the result and print a message on failure. + bool check(bool result, char const* fmt, ...); + + /// Directly assign status. + self& operator = (int status) { *_status = status; return *this; } + }; + + bool + TestBox::check(bool result, char const* fmt, ...) { + if (!result) { + static size_t const N = 1<<16; + char buffer[N]; // just stack, go big. + va_list ap; + va_start(ap, fmt); + vsnprintf(buffer, N, fmt, ap); + va_end(ap); + rprintf(_test, "%s\n", buffer); + *_status = REGRESSION_TEST_FAILED; + } + return result; + } +} +#endif // TS_TEST_BOX_HEADER
