15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_connection_helper.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/test_tools/mock_clock.h" 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/quic/test_tools/mock_random.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/test_tools/test_task_runner.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace test { 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochclass TestDelegate : public QuicAlarm::Delegate { 17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch public: 18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TestDelegate() : fired_(false) {} 19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch virtual QuicTime OnAlarm() OVERRIDE { 21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch fired_ = true; 22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return QuicTime::Zero(); 23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool fired() const { return fired_; } 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void Clear() { fired_= false; } 27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private: 29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool fired_; 30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}; 31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class QuicConnectionHelperTest : public ::testing::Test { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicConnectionHelperTest() 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : runner_(new TestTaskRunner(&clock_)), 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) helper_(runner_.get(), &clock_, &random_generator_) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<TestTaskRunner> runner_; 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) QuicConnectionHelper helper_; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockClock clock_; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRandom random_generator_; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(QuicConnectionHelperTest, GetClock) { 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(&clock_, helper_.GetClock()); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(QuicConnectionHelperTest, GetRandomGenerator) { 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(&random_generator_, helper_.GetRandomGenerator()); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST_F(QuicConnectionHelperTest, CreateAlarm) { 54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TestDelegate* delegate = new TestDelegate(); 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate)); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); 58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alarm->Set(clock_.Now().Add(delta)); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Verify that the alarm task has been posted. 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1u, runner_->GetPostedTasks().size()); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()), 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) runner_->GetPostedTasks()[0].delay); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runner_->RunNextTask(); 66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); 67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_TRUE(delegate->fired()); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST_F(QuicConnectionHelperTest, CreateAlarmAndCancel) { 71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TestDelegate* delegate = new TestDelegate(); 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate)); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); 75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alarm->Set(clock_.Now().Add(delta)); 76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alarm->Cancel(); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // The alarm task should still be posted. 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1u, runner_->GetPostedTasks().size()); 80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()), 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) runner_->GetPostedTasks()[0].delay); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) runner_->RunNextTask(); 84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); 85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_FALSE(delegate->fired()); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochTEST_F(QuicConnectionHelperTest, CreateAlarmAndReset) { 89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TestDelegate* delegate = new TestDelegate(); 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate)); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); 93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alarm->Set(clock_.Now().Add(delta)); 94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alarm->Cancel(); 95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); 96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alarm->Set(clock_.Now().Add(new_delta)); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // The alarm task should still be posted. 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1u, runner_->GetPostedTasks().size()); 100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()), 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) runner_->GetPostedTasks()[0].delay); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) runner_->RunNextTask(); 104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); 105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_FALSE(delegate->fired()); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // The alarm task should be posted again. 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1u, runner_->GetPostedTasks().size()); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) runner_->RunNextTask(); 111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now()); 112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch EXPECT_TRUE(delegate->fired()); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(QuicConnectionHelperTest, CreateAlarmAndResetEarlier) { 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) TestDelegate* delegate = new TestDelegate(); 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate)); 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(3); 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) alarm->Set(clock_.Now().Add(delta)); 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) alarm->Cancel(); 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(1); 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) alarm->Set(clock_.Now().Add(new_delta)); 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Both alarm tasks will be posted. 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(2u, runner_->GetPostedTasks().size()); 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The earlier task will execute and will fire the alarm-> 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) runner_->RunNextTask(); 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now()); 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_TRUE(delegate->fired()); 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delegate->Clear(); 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The latter task is still posted. 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1u, runner_->GetPostedTasks().size()); 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // When the latter task is executed, the weak ptr will be invalid and 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the alarm will not fire. 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) runner_->RunNextTask(); 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now()); 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_FALSE(delegate->fired()); 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(QuicConnectionHelperTest, CreateAlarmAndUpdate) { 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) TestDelegate* delegate = new TestDelegate(); 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate)); 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const QuicClock* clock = helper_.GetClock(); 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicTime start = clock->Now(); 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1); 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) alarm->Set(clock->Now().Add(delta)); 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3); 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) alarm->Update(clock->Now().Add(new_delta), 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicTime::Delta::FromMicroseconds(1)); 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The alarm task should still be posted. 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ASSERT_EQ(1u, runner_->GetPostedTasks().size()); 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()), 15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_->GetPostedTasks()[0].delay); 16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_->RunNextTask(); 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_EQ(QuicTime::Zero().Add(delta), clock->Now()); 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_FALSE(delegate->fired()); 16403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Move the alarm forward 1us and ensure it doesn't move forward. 16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) alarm->Update(clock->Now().Add(new_delta), 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicTime::Delta::FromMicroseconds(2)); 16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 16903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ASSERT_EQ(1u, runner_->GetPostedTasks().size()); 17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_EQ( 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::TimeDelta::FromMicroseconds( 17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_delta.Subtract(delta).ToMicroseconds()), 17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_->GetPostedTasks()[0].delay); 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) runner_->RunNextTask(); 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_EQ(start.Add(new_delta), clock->Now()); 17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_TRUE(delegate->fired()); 17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Set the alarm via an update call. 17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_delta = QuicTime::Delta::FromMicroseconds(5); 18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) alarm->Update(clock->Now().Add(new_delta), 18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) QuicTime::Delta::FromMicroseconds(1)); 18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_TRUE(alarm->IsSet()); 18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Update it with an uninitialized time and ensure it's cancelled. 18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) alarm->Update(QuicTime::Zero(), QuicTime::Delta::FromMicroseconds(1)); 18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) EXPECT_FALSE(alarm->IsSet()); 18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace test 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 192