A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tcp-rate-ops-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 NITK Surathkal
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Vivek Jain <jain.vivek.anand@gmail.com>
7 * Viyom Mittal <viyommittal@gmail.com>
8 * Mohit P. Tahiliani <tahiliani@nitk.edu.in>
9 */
10
11#include "tcp-error-model.h"
12#include "tcp-general-test.h"
13
14#include "ns3/config.h"
15#include "ns3/log.h"
16#include "ns3/tcp-rate-ops.h"
17#include "ns3/tcp-tx-buffer.h"
18#include "ns3/tcp-tx-item.h"
19#include "ns3/test.h"
20
21using namespace ns3;
22
23NS_LOG_COMPONENT_DEFINE("TcpRateOpsTestSuite");
24
26
27/**
28 * @ingroup internet-test
29 * @ingroup tests
30 *
31 * @brief The TcpRateLinux Basic Test
32 */
34{
35 public:
36 /**
37 * Constructor
38 * @param cWnd Congestion window size
39 * @param tailSeq Tail sequence number
40 * @param nextTx Tx next sequence number
41 * @param testCase test case type
42 * @param testName test name
43 */
45 SequenceNumber32 tailSeq,
46 SequenceNumber32 nextTx,
47 uint32_t testCase,
48 std::string testName);
49
50 private:
51 void DoRun() override;
52
53 /**
54 * Send an application packet
55 * @param skb the data to send
56 */
57 void SendSkb(TcpTxItem* skb);
58 /**
59 * Deliver an application packet
60 * @param skb the data to deliver
61 */
62 void SkbDelivered(TcpTxItem* skb);
63
64 TcpRateLinux m_rateOps; //!< Rate information for TCP
65 uint32_t m_cWnd; //!< Congestion window size
66 uint32_t m_inFlight; //!< Number of packets in-flight
67 uint32_t m_segmentSize; //!< Segment size
68 uint32_t m_delivered; //!< Number of segments delivered
69 Time m_deliveredTime; //!< Last time of a delivery
70 SequenceNumber32 m_tailSeq; //!< Tail sequence number
71 SequenceNumber32 m_nextTx; //!< Tx next sequence number
72 uint32_t m_testCase; //!< Test case type
73 std::vector<TcpTxItem*> m_skbs; //!< Application packets
74};
75
77 SequenceNumber32 tailSeq,
78 SequenceNumber32 nextTx,
79 uint32_t testCase,
80 std::string testName)
81 : TestCase(testName),
82 m_cWnd(cWnd),
83 m_inFlight(0),
85 m_delivered(0),
87 m_tailSeq(tailSeq),
88 m_nextTx(nextTx),
89 m_testCase(testCase)
90{
91}
92
93void
95{
96 for (uint8_t i = 0; i < 100; ++i)
97 {
98 m_skbs.push_back(new TcpTxItem());
100 }
101
102 for (uint8_t i = 0; i < 100; ++i)
103 {
104 Simulator::Schedule(Seconds((i + 1) * 0.1),
106 this,
107 m_skbs[i]);
108 }
109
112
113 for (uint8_t i = 0; i < 100; ++i)
114 {
115 delete m_skbs[i];
116 }
117}
118
119void
121{
122 bool isStartOfTransmission = m_inFlight == 0;
123 m_rateOps.CalculateAppLimited(m_cWnd, m_inFlight, m_segmentSize, m_tailSeq, m_nextTx, 0, 0);
124 m_rateOps.SkbSent(skb, isStartOfTransmission);
125 m_inFlight += skb->GetSeqSize();
126
129 "SKB should have delivered equal to current value of total delivered");
130
131 if (isStartOfTransmission)
132 {
135 "SKB should have updated the delivered time to current value");
136 }
137 else
138 {
141 "SKB should have updated the delivered time to current value");
142 }
143}
144
145void
147{
148 m_rateOps.SkbDelivered(skb);
149 m_inFlight -= skb->GetSeqSize();
150 m_delivered += skb->GetSeqSize();
152
154 Time::Max(),
155 "SKB should have delivered time as Time::Max ()");
156
157 if (m_testCase == 1)
158 {
160 false,
161 "Socket should not be applimited");
162 }
163 else if (m_testCase == 2)
164 {
166 true,
167 "Socket should be applimited");
168 }
169}
170
171/**
172 * @ingroup internet-test
173 *
174 * @brief Behaves as NewReno except HasCongControl returns true
175 */
177{
178 public:
179 /**
180 * @brief Get the type ID.
181 * @return the object TypeId
182 */
183 static TypeId GetTypeId();
184
186 {
187 }
188
189 bool HasCongControl() const override
190 {
191 return true;
192 }
193};
194
195TypeId
197{
198 static TypeId tid = TypeId("ns3::MimicCongControl")
200 .AddConstructor<MimicCongControl>()
201 .SetGroupName("Internet");
202 return tid;
203}
204
205/**
206 * @ingroup internet-test
207 * @ingroup tests
208 *
209 * @brief The TcpRateLinux Test uses sender-receiver model to test its functionality.
210 * This test case uses the bytes inflight trace to check whether rate sample
211 * correctly sets the value of m_deliveredTime and m_firstSentTime. This is
212 * done using rate trace. Further, Using Rx trace, m_isDupAck is maintained to
213 * track duplicate acknowledgments. This, in turn, is used to see whether rate
214 * sample is updated properly (in case of SACK) or not (in case of non SACK).
215 */
217{
218 public:
219 /**
220 * @brief Constructor.
221 * @param desc Description.
222 * @param sackEnabled To use SACK or not
223 * @param toDrop Packets to drop.
224 */
225 TcpRateLinuxWithSocketsTest(const std::string& desc,
226 bool sackEnabled,
227 std::vector<uint32_t>& toDrop);
228
229 protected:
230 /**
231 * @brief Create and install the socket to install on the sender
232 * @param node sender node pointer
233 * @return the socket to be installed in the sender
234 */
236
237 /**
238 * @brief Create a receiver error model.
239 * @returns The receiver error model.
240 */
242
243 /**
244 * @brief Receive a packet.
245 * @param p The packet.
246 * @param h The TCP header.
247 * @param who Who the socket belongs to (sender or receiver).
248 */
249 void Rx(const Ptr<const Packet> p, const TcpHeader& h, SocketWho who) override;
250
251 /**
252 * @brief Track the bytes in flight.
253 * @param oldValue previous value.
254 * @param newValue actual value.
255 */
256 void BytesInFlightTrace(uint32_t oldValue, uint32_t newValue) override;
257
258 /**
259 * @brief Called when a packet is dropped.
260 * @param ipH The IP header.
261 * @param tcpH The TCP header.
262 * @param p The packet.
263 */
264 void PktDropped(const Ipv4Header& ipH, const TcpHeader& tcpH, Ptr<const Packet> p);
265
266 /**
267 * @brief Configure the test.
268 */
269 void ConfigureEnvironment() override;
270
271 /**
272 * @brief Do the final checks.
273 */
274 void FinalChecks() override;
275
276 /**
277 * @brief Track the rate value of TcpRateLinux.
278 * @param rate updated value of TcpRate.
279 */
280 void RateUpdatedTrace(const TcpRateLinux::TcpRateConnection& rate) override;
281
282 /**
283 * @brief Track the rate sample value of TcpRateLinux.
284 * @param sample updated value of TcpRateSample.
285 */
286 void RateSampleUpdatedTrace(const TcpRateLinux::TcpRateSample& sample) override;
287
288 private:
289 Ptr<MimicCongControl> m_congCtl; //!< Dummy congestion control.
290 bool m_sackEnabled; //!< Sack Variable
291 std::vector<uint32_t> m_toDrop; //!< List of SequenceNumber to drop
292 uint32_t m_bytesInFlight{0}; //!< Bytes inflight
294 bool m_isDupAck; //!< Whether ACK is DupAck
297};
298
300 bool sackEnabled,
301 std::vector<uint32_t>& toDrop)
302 : TcpGeneralTest(desc),
303 m_sackEnabled(sackEnabled),
304 m_toDrop(toDrop)
305{
306}
307
316
317void
327
330{
332 for (auto it = m_toDrop.begin(); it != m_toDrop.end(); ++it)
333 {
334 m_errorModel->AddSeqToKill(SequenceNumber32(*it));
335 }
336
337 m_errorModel->SetDropCallback(MakeCallback(&TcpRateLinuxWithSocketsTest::PktDropped, this));
338
339 return m_errorModel;
340}
341
342void
344 const TcpHeader& tcpH,
346{
347 NS_LOG_DEBUG("Drop seq= " << tcpH.GetSequenceNumber() << " size " << p->GetSize());
348}
349
350void
352{
353 if (who == SENDER)
354 {
356 (h.GetFlags() & TcpHeader::FIN) == 0)
357 {
358 m_isDupAck = true;
359 }
360 else
361 {
362 m_isDupAck = false;
364 }
365 }
366}
367
368void
370{
371 m_bytesInFlight = newValue;
372}
373
374void
376{
377 NS_LOG_DEBUG("Rate updated " << rate);
378 if (m_bytesInFlight == 0)
379 {
382 "FirstSentTime should be current time when bytes inflight is zero");
385 "Delivered time should be current time when bytes inflight is zero");
386 }
388 m_prevRate.m_delivered,
389 "Total delivered should not be lesser than previous values");
390 m_prevRate = rate;
391}
392
393void
395{
396 NS_LOG_DEBUG("Rate sample updated " << sample);
397 if (m_isDupAck)
398 {
399 if (!m_sackEnabled)
400 {
402 sample,
403 "RateSample should not update due to DupAcks");
404 }
405 else
406 {
407 if (sample.m_ackedSacked == 0)
408 {
410 sample,
411 "RateSample should not update as nothing is acked or sacked");
412 }
413 }
414 }
415 m_prevRateSample = sample;
416}
417
418void
422
423/**
424 * @ingroup internet-test
425 * @ingroup tests
426 *
427 * @brief The TcpRateLinuxWithBufferTest tests rate sample functionality with arbitrary SACK
428 * scenario. Check the value of delivered against a home-made guess
429 */
431{
432 public:
433 /**
434 * @brief Constructor.
435 * @param segmentSize Segment size to use.
436 * @param desc Description.
437 */
439
440 private:
441 void DoRun() override;
442 void DoTeardown() override;
443
444 /**
445 * @brief Track the rate value of TcpRateLinux.
446 * @param rate updated value of TcpRate.
447 */
448 virtual void RateUpdatedTrace(const TcpRateLinux::TcpRateConnection& rate);
449
450 /**
451 * @brief Track the rate sample value of TcpRateLinux.
452 * @param sample updated value of TcpRateSample.
453 */
454 virtual void RateSampleUpdatedTrace(const TcpRateLinux::TcpRateSample& sample);
455
456 /** @brief Test with acks without drop */
458
459 /** @brief Test with arbitrary SACK scenario */
460 void TestWithSackBlocks();
461
462 uint32_t m_expectedDelivered{0}; //!< Amount of expected delivered data
463 uint32_t m_expectedAckedSacked{0}; //!< Amount of expected acked sacked data
464 uint32_t m_segmentSize; //!< Segment size
465 TcpTxBuffer m_txBuf; //!< Tcp Tx buffer
466 Ptr<TcpRateOps> m_rateOps; //!< Rate operations
467};
468
470 : TestCase(testString),
472{
474 m_rateOps->TraceConnectWithoutContext(
475 "TcpRateUpdated",
477 m_rateOps->TraceConnectWithoutContext(
478 "TcpRateSampleUpdated",
480}
481
482void
489
490void
492{
493 NS_LOG_DEBUG("Rate updated " << rate);
496 "Delivered data is not equal to expected delivered");
497}
498
499void
501{
502 NS_LOG_DEBUG("Rate sample updated " << sample);
505 "AckedSacked bytes is not equal to expected AckedSacked bytes");
506}
507
508void
510{
511 SequenceNumber32 head(1);
512 m_txBuf.SetHeadSequence(head);
515 m_txBuf.SetSegmentSize(m_segmentSize);
516 m_txBuf.SetDupAckThresh(3);
517
519
520 // Send 10 Segments
521 for (uint8_t i = 0; i < 10; ++i)
522 {
523 bool isStartOfTransmission = m_txBuf.BytesInFlight() == 0;
524 TcpTxItem* outItem =
525 m_txBuf.CopyFromSequence(m_segmentSize, SequenceNumber32((i * m_segmentSize) + 1));
526 m_rateOps->SkbSent(outItem, isStartOfTransmission);
527 }
528
529 uint32_t priorInFlight = m_txBuf.BytesInFlight();
530 // ACK 2 Segments
531 for (uint8_t i = 1; i <= 2; ++i)
532 {
533 priorInFlight = m_txBuf.BytesInFlight();
535 m_txBuf.DiscardUpTo(SequenceNumber32(m_segmentSize * i + 1),
538 m_rateOps->GenerateSample(m_segmentSize, 0, false, priorInFlight, Seconds(0));
539 }
540
541 priorInFlight = m_txBuf.BytesInFlight();
542 sack->AddSackBlock(TcpOptionSack::SackBlock(SequenceNumber32(m_segmentSize * 4 + 1),
545 m_txBuf.Update(sack->GetSackList(), MakeCallback(&TcpRateOps::SkbDelivered, m_rateOps));
547 m_rateOps->GenerateSample(m_segmentSize, 0, false, priorInFlight, Seconds(0));
548
549 priorInFlight = m_txBuf.BytesInFlight();
550 sack->AddSackBlock(TcpOptionSack::SackBlock(SequenceNumber32(m_segmentSize * 3 + 1),
553 m_txBuf.Update(sack->GetSackList(), MakeCallback(&TcpRateOps::SkbDelivered, m_rateOps));
554 m_rateOps->GenerateSample(m_segmentSize, 0, false, priorInFlight, Seconds(0));
555
556 priorInFlight = m_txBuf.BytesInFlight();
557 // Actual delivered should be increased by one segment even multiple blocks are acked.
559 m_txBuf.DiscardUpTo(SequenceNumber32(m_segmentSize * 5 + 1),
561 m_rateOps->GenerateSample(m_segmentSize, 0, false, priorInFlight, Seconds(0));
562
563 priorInFlight = m_txBuf.BytesInFlight();
564 // ACK rest of the segments
565 for (uint8_t i = 6; i <= 10; ++i)
566 {
568 m_txBuf.DiscardUpTo(SequenceNumber32(m_segmentSize * i + 1),
570 }
572 TcpRateOps::TcpRateSample rateSample =
573 m_rateOps->GenerateSample(5 * m_segmentSize, 0, false, priorInFlight, Seconds(0));
574}
575
576void
580
581/**
582 * @ingroup internet-test
583 *
584 * @brief the TestSuite for the TcpRateLinux test case
585 */
587{
588 public:
590 : TestSuite("tcp-rate-ops", Type::UNIT)
591 {
595 1,
596 "Testing SkbDelivered and SkbSent"),
599 new TcpRateLinuxBasicTest(1000,
602 2,
603 "Testing SkbDelivered and SkbSent with app limited data"),
605
606 std::vector<uint32_t> toDrop;
607 toDrop.push_back(4001);
609 new TcpRateLinuxWithSocketsTest("Checking Rate sample value without SACK, one drop",
610 false,
611 toDrop),
613
615 new TcpRateLinuxWithSocketsTest("Checking Rate sample value with SACK, one drop",
616 true,
617 toDrop),
619 toDrop.push_back(4001);
621 new TcpRateLinuxWithSocketsTest("Checking Rate sample value without SACK, two drop",
622 false,
623 toDrop),
625
627 new TcpRateLinuxWithSocketsTest("Checking Rate sample value with SACK, two drop",
628 true,
629 toDrop),
631
634 "Checking rate sample values with arbitrary SACK Block"),
636
639 "Checking rate sample values with arbitrary SACK Block"),
641 }
642};
643
644static TcpRateOpsTestSuite g_TcpRateOpsTestSuite; //!< Static variable for test initialization
Behaves as NewReno except HasCongControl returns true.
static TypeId GetTypeId()
Get the type ID.
bool HasCongControl() const override
Returns true when Congestion Control Algorithm implements CongControl.
The TcpRateLinux Basic Test.
void SkbDelivered(TcpTxItem *skb)
Deliver an application packet.
uint32_t m_delivered
Number of segments delivered.
void SendSkb(TcpTxItem *skb)
Send an application packet.
uint32_t m_segmentSize
Segment size.
TcpRateLinux m_rateOps
Rate information for TCP.
Time m_deliveredTime
Last time of a delivery.
uint32_t m_testCase
Test case type.
uint32_t m_inFlight
Number of packets in-flight.
uint32_t m_cWnd
Congestion window size.
TcpRateLinuxBasicTest(uint32_t cWnd, SequenceNumber32 tailSeq, SequenceNumber32 nextTx, uint32_t testCase, std::string testName)
Constructor.
SequenceNumber32 m_tailSeq
Tail sequence number.
void DoRun() override
Implementation to actually run this TestCase.
std::vector< TcpTxItem * > m_skbs
Application packets.
SequenceNumber32 m_nextTx
Tx next sequence number.
The TcpRateLinuxWithBufferTest tests rate sample functionality with arbitrary SACK scenario.
uint32_t m_expectedAckedSacked
Amount of expected acked sacked data.
void DoRun() override
Implementation to actually run this TestCase.
void TestWithStraightAcks()
Test with acks without drop.
TcpTxBuffer m_txBuf
Tcp Tx buffer.
virtual void RateUpdatedTrace(const TcpRateLinux::TcpRateConnection &rate)
Track the rate value of TcpRateLinux.
TcpRateLinuxWithBufferTest(uint32_t segmentSize, std::string desc)
Constructor.
virtual void RateSampleUpdatedTrace(const TcpRateLinux::TcpRateSample &sample)
Track the rate sample value of TcpRateLinux.
void TestWithSackBlocks()
Test with arbitrary SACK scenario.
Ptr< TcpRateOps > m_rateOps
Rate operations.
uint32_t m_expectedDelivered
Amount of expected delivered data.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_segmentSize
Segment size.
The TcpRateLinux Test uses sender-receiver model to test its functionality.
void PktDropped(const Ipv4Header &ipH, const TcpHeader &tcpH, Ptr< const Packet > p)
Called when a packet is dropped.
TcpRateLinuxWithSocketsTest(const std::string &desc, bool sackEnabled, std::vector< uint32_t > &toDrop)
Constructor.
void Rx(const Ptr< const Packet > p, const TcpHeader &h, SocketWho who) override
Receive a packet.
Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node) override
Create and install the socket to install on the sender.
bool m_isDupAck
Whether ACK is DupAck.
void BytesInFlightTrace(uint32_t oldValue, uint32_t newValue) override
Track the bytes in flight.
void ConfigureEnvironment() override
Configure the test.
void FinalChecks() override
Do the final checks.
void RateSampleUpdatedTrace(const TcpRateLinux::TcpRateSample &sample) override
Track the rate sample value of TcpRateLinux.
SequenceNumber32 m_lastAckRecv
Last ACK received.
TcpRateLinux::TcpRateSample m_prevRateSample
Previous rate sample.
std::vector< uint32_t > m_toDrop
List of SequenceNumber to drop.
Ptr< ErrorModel > CreateReceiverErrorModel() override
Create a receiver error model.
uint32_t m_bytesInFlight
Bytes inflight.
void RateUpdatedTrace(const TcpRateLinux::TcpRateConnection &rate) override
Track the rate value of TcpRateLinux.
TcpRateLinux::TcpRateConnection m_prevRate
Previous rate.
Ptr< MimicCongControl > m_congCtl
Dummy congestion control.
the TestSuite for the TcpRateLinux test case
Packet header for IPv4.
Definition ipv4-header.h:23
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
virtual Ptr< TcpSocketMsgBase > CreateSenderSocket(Ptr< Node > node)
Create and install the socket to install on the sender.
void SetPropagationDelay(Time propDelay)
Propagation delay of the bottleneck link.
void SetAppPktCount(uint32_t pktCount)
Set app packet count.
SocketWho
Used as parameter of methods, specifies on what node the caller is interested (e.g.
virtual void ConfigureEnvironment()
Change the configuration of the environment.
TcpGeneralTest(const std::string &desc)
TcpGeneralTest constructor.
void SetTransmitStart(Time startTime)
Set the initial time at which the application sends the first data packet.
Header for the Transmission Control Protocol.
Definition tcp-header.h:36
SequenceNumber32 GetSequenceNumber() const
Get the sequence number.
uint8_t GetFlags() const
Get the flags.
SequenceNumber32 GetAckNumber() const
Get the ACK number.
std::pair< SequenceNumber32, SequenceNumber32 > SackBlock
SACK block definition.
Linux management and generation of Rate information for TCP.
virtual void SkbDelivered(TcpTxItem *skb)=0
Update the Rate information after an item is received.
Tcp sender buffer.
Item that encloses the application packet and some flags for it.
Definition tcp-tx-item.h:22
uint32_t GetSeqSize() const
Get the size in the sequence number space.
RateInformation & GetRateInformation()
Get (to modify) the Rate Information of this item.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
@ QUICK
Fast test.
Definition test.h:1055
TestCase(const TestCase &)=delete
Type
Type of test.
Definition test.h:1274
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:490
static constexpr auto UNIT
Definition test.h:1291
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition nstime.h:286
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
uint32_t segmentSize
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:886
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
SequenceNumber< uint32_t, int32_t > SequenceNumber32
32 bit Sequence number.
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_ASSERT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to a limit and report and abort if not.
Definition test.h:905
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Information about the connection rate.
Time m_deliveredTime
Simulator time when m_delivered was last updated.
uint64_t m_delivered
The total amount of data in bytes delivered so far.
Time m_firstSentTime
The send time of the packet that was most recently marked as delivered.
Rate Sample structure.
uint32_t m_ackedSacked
The amount of data acked and sacked in the last received ack.
bool m_isAppLimited
Connection's app limited at the time the packet was sent.
Definition tcp-tx-item.h:83
uint64_t m_delivered
Connection's delivered data at the time the packet was sent.
Definition tcp-tx-item.h:78
Time m_deliveredTime
Connection's delivered time at the time the packet was sent.
Definition tcp-tx-item.h:79
static TcpRateOpsTestSuite g_TcpRateOpsTestSuite
Static variable for test initialization.