ProteoWizard
BinaryIndexStreamTest.cpp
Go to the documentation of this file.
1//
2// $Id$
3//
4//
5// Original author: Matt Chambers <matt.chambers .@. vanderbilt.edu>
6//
7// Copyright 2009 Vanderbilt University - Nashville, TN 37232
8//
9// Licensed under the Apache License, Version 2.0 (the "License");
10// you may not use this file except in compliance with the License.
11// You may obtain a copy of the License at
12//
13// http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20//
21
22#include "BinaryIndexStream.hpp"
25#include "boost/thread/thread.hpp"
26#include "boost/thread/barrier.hpp"
27
28
29using namespace pwiz::util;
30using namespace pwiz::data;
31
32ostream* os_ = 0;
33
34
35void test()
36{
37 if (os_) cout << "Testing BinaryIndexStream (single thread)" << endl;
38
39 shared_ptr<stringstream> indexStreamPtr(new stringstream);
40
41 // test initial creation and usage of the index stream
42 {
43 vector<Index::Entry> entries;
44 for (size_t i=0; i < 10; ++i)
45 {
46 Index::Entry entry;
47 entry.id = lexical_cast<string>(i);
48 entry.index = i;
49 entry.offset = i*100;
50 entries.push_back(entry);
51 }
52
53 BinaryIndexStream index(indexStreamPtr);
54 unit_assert(index.size() == 0);
55 unit_assert(!index.find("42").get());
56 unit_assert(!index.find(42).get());
57
58 index.create(entries);
59 unit_assert(index.size() == 10);
60
61 for (size_t i=0; i < 10; ++i)
62 {
63 Index::EntryPtr entryPtr = index.find(i);
64 unit_assert(entryPtr.get());
65 unit_assert(entryPtr->id == lexical_cast<string>(i));
66 unit_assert(entryPtr->index == i);
67 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
68
69 entryPtr = index.find(entryPtr->id);
70 unit_assert(entryPtr.get());
71 unit_assert(entryPtr->id == lexical_cast<string>(i));
72 unit_assert(entryPtr->index == i);
73 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
74 }
75
76 unit_assert(!index.find("42").get());
77 unit_assert(!index.find(42).get());
78 }
79
80 // test re-use of an existing index stream
81 {
82 BinaryIndexStream index(indexStreamPtr);
83 unit_assert(index.size() == 10);
84 unit_assert(!index.find("42").get());
85 unit_assert(!index.find(42).get());
86
87 for (size_t i=0; i < 10; ++i)
88 {
89 Index::EntryPtr entryPtr = index.find(i);
90 unit_assert(entryPtr.get());
91 unit_assert(entryPtr->id == lexical_cast<string>(i));
92 unit_assert(entryPtr->index == i);
93 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
94
95 entryPtr = index.find(entryPtr->id);
96 unit_assert(entryPtr.get());
97 unit_assert(entryPtr->id == lexical_cast<string>(i));
98 unit_assert(entryPtr->index == i);
99 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
100 }
101
102 unit_assert(!index.find("42").get());
103 unit_assert(!index.find(42).get());
104 }
105
106 // test creating a new, smaller index in an existing index stream
107 {
108 vector<Index::Entry> entries;
109 for (size_t i=0; i < 5; ++i)
110 {
111 Index::Entry entry;
112 entry.id = lexical_cast<string>(i);
113 entry.index = i;
114 entry.offset = i*100;
115 entries.push_back(entry);
116 }
117
118 BinaryIndexStream index(indexStreamPtr);
119
120 unit_assert(index.size() == 10);
121 index.create(entries);
122 unit_assert(index.size() == 5);
123
124 for (size_t i=0; i < 5; ++i)
125 {
126 Index::EntryPtr entryPtr = index.find(i);
127 unit_assert(entryPtr.get());
128 unit_assert(entryPtr->id == lexical_cast<string>(i));
129 unit_assert(entryPtr->index == i);
130 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
131
132 entryPtr = index.find(entryPtr->id);
133 unit_assert(entryPtr.get());
134 unit_assert(entryPtr->id == lexical_cast<string>(i));
135 unit_assert(entryPtr->index == i);
136 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
137 }
138
139 unit_assert(!index.find("5").get());
140 unit_assert(!index.find(5).get());
141 }
142}
143
144
145void testThreadSafetyWorker(boost::barrier* testBarrier, BinaryIndexStream* testIndex)
146{
147 testBarrier->wait(); // wait until all threads have started
148 BinaryIndexStream& index = *testIndex;
149
150 try
151 {
152 for (size_t i=0; i < 10; ++i)
153 {
154 Index::EntryPtr entryPtr = index.find(i);
155 unit_assert(entryPtr.get());
156 unit_assert(entryPtr->id == lexical_cast<string>(i));
157 unit_assert(entryPtr->index == i);
158 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
159
160 entryPtr = index.find(entryPtr->id);
161 unit_assert(entryPtr.get());
162 unit_assert(entryPtr->id == lexical_cast<string>(i));
163 unit_assert(entryPtr->index == i);
164 unit_assert(entryPtr->offset == Index::stream_offset(i*100));
165 }
166
167 unit_assert(!index.find("42").get());
168 unit_assert(!index.find(42).get());
169 }
170 catch (exception& e)
171 {
172 cerr << e.what() << endl;
173 }
174 catch (...)
175 {
176 cerr << "Caught unknown exception." << endl;
177 }
178}
179
181{
182 if (os_) cout << "Testing BinaryIndexStream (multithreaded)" << endl;
183
184 shared_ptr<stringstream> indexStreamPtr(new stringstream);
185
186 // create a shared index stream
187 vector<Index::Entry> entries;
188 for (size_t i=0; i < 10; ++i)
189 {
190 Index::Entry entry;
191 entry.id = lexical_cast<string>(i);
192 entry.index = i;
193 entry.offset = i*100;
194 entries.push_back(entry);
195 }
196
197 BinaryIndexStream index(indexStreamPtr);
198 index.create(entries);
199 unit_assert(index.size() == 10);
200
201 // create workers to test using the stream
202 const int testThreadCount = 100;
203 boost::barrier testBarrier(testThreadCount);
204 boost::thread_group testThreadGroup;
205 for (int i=0; i < testThreadCount; ++i)
206 testThreadGroup.add_thread(new boost::thread(&testThreadSafetyWorker, &testBarrier, &index));
207 testThreadGroup.join_all();
208}
209
210
211int main(int argc, char* argv[])
212{
213 TEST_PROLOG(argc, argv)
214
215 try
216 {
217 if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout;
218 test();
220 }
221 catch (exception& e)
222 {
223 TEST_FAILED(e.what())
224 }
225 catch (...)
226 {
227 TEST_FAILED("Caught unknown exception.")
228 }
229
231}
int main(int argc, char *argv[])
void testThreadSafetyWorker(boost::barrier *testBarrier, BinaryIndexStream *testIndex)
void testThreadSafety()
ostream * os_
void test()
index implementation in a stream (intended for fstreams but any iostream works); find(string id) is O...
virtual EntryPtr find(const std::string &id) const
returns the entry for the specified string id, or null if the id is not in the index
virtual size_t size() const
returns the number of entries in the index
virtual void create(std::vector< Entry > &entries)
create the index from specified list of entries; the list is non-const because the index implementati...
boost::shared_ptr< Entry > EntryPtr
Definition Index.hpp:53
boost::iostreams::stream_offset stream_offset
Definition Index.hpp:43
generic type identifying an indexed item by string id, ordinal index, and stream offset
Definition Index.hpp:47
std::string id
Definition Index.hpp:48
boost::uint64_t index
Definition Index.hpp:49
stream_offset offset
Definition Index.hpp:50
#define unit_assert(x)
Definition unit.hpp:85
#define TEST_EPILOG
Definition unit.hpp:183
#define TEST_FAILED(x)
Definition unit.hpp:177
#define TEST_PROLOG(argc, argv)
Definition unit.hpp:175