summaryrefslogtreecommitdiff
path: root/xdelta3/testing/modify.h
diff options
context:
space:
mode:
authorjosh.macdonald <jmacd@users.noreply.github.com>2008-07-08 04:07:45 +0000
committerjosh.macdonald <jmacd@users.noreply.github.com>2008-07-08 04:07:45 +0000
commitd0c5ff7a1847558a9264d9485e336f549b66dd38 (patch)
treed19851cb1d698cb1d7ea6046ab5333ad0258323b /xdelta3/testing/modify.h
parent2f8593b1222a6e74c835a1b90e4195de0ba234d0 (diff)
Add testing for move/copy mutators.
Diffstat (limited to 'xdelta3/testing/modify.h')
-rw-r--r--xdelta3/testing/modify.h119
1 files changed, 112 insertions, 7 deletions
diff --git a/xdelta3/testing/modify.h b/xdelta3/testing/modify.h
index 2f3e752..ac2286a 100644
--- a/xdelta3/testing/modify.h
+++ b/xdelta3/testing/modify.h
@@ -14,8 +14,9 @@ public:
14 enum Kind { 14 enum Kind {
15 MODIFY = 1, 15 MODIFY = 1,
16 ADD = 2, 16 ADD = 2,
17 MOVE = 3, 17 DELETE = 3,
18 DELETE = 4, 18 MOVE = 4,
19 COPY = 5,
19 }; 20 };
20 21
21 // Constructor for modify, add, delete. 22 // Constructor for modify, add, delete.
@@ -23,15 +24,16 @@ public:
23 : kind(kind), 24 : kind(kind),
24 size(size), 25 size(size),
25 addr1(addr1) { 26 addr1(addr1) {
26 CHECK_NE(kind, MOVE); 27 CHECK(kind != MOVE && kind != COPY);
27 } 28 }
28 29
29 // Constructor for move 30 // Constructor for move
30 Change(Kind kind, xoff_t size, xoff_t addr1, xoff_t addr2) 31 Change(Kind kind, xoff_t size, xoff_t addr1, xoff_t addr2)
31 : kind(kind), 32 : kind(kind),
32 size(size), 33 size(size),
33 addr1(addr1) { 34 addr1(addr1),
34 CHECK_EQ(kind, MOVE); 35 addr2(addr2) {
36 CHECK(kind == MOVE || kind == COPY);
35 } 37 }
36 38
37 Kind kind; 39 Kind kind;
@@ -78,6 +80,17 @@ public:
78 const SegmentMap *source_table, 80 const SegmentMap *source_table,
79 MTRandom *rand); 81 MTRandom *rand);
80 82
83 static void CopyChange(const Change &ch,
84 SegmentMap *table,
85 const SegmentMap *source_table,
86 MTRandom *rand);
87
88 static void AppendCopy(SegmentMap *table,
89 const SegmentMap *source_table,
90 xoff_t copy_offset,
91 xoff_t append_offset,
92 xoff_t length);
93
81 ChangeList* Changes() { 94 ChangeList* Changes() {
82 return &cl_; 95 return &cl_;
83 } 96 }
@@ -119,11 +132,14 @@ void ChangeListMutator::Mutate(const Change &ch,
119 case Change::DELETE: 132 case Change::DELETE:
120 DeleteChange(ch, table, source_table, rand); 133 DeleteChange(ch, table, source_table, rand);
121 break; 134 break;
135 case Change::COPY:
136 CopyChange(ch, table, source_table, rand);
137 break;
122 case Change::MOVE: 138 case Change::MOVE:
123 //MoveChange(ch, table, source_table, rand); 139 MoveChange(ch, table, source_table, rand);
124 break; 140 break;
125 } 141 }
126} 142}
127 143
128void ChangeListMutator::ModifyChange(const Change &ch, 144void ChangeListMutator::ModifyChange(const Change &ch,
129 SegmentMap *table, 145 SegmentMap *table,
@@ -258,6 +274,95 @@ void ChangeListMutator::DeleteChange(const Change &ch,
258 CHECK_LE(m_end, i_end); 274 CHECK_LE(m_end, i_end);
259} 275}
260 276
277void ChangeListMutator::MoveChange(const Change &ch,
278 SegmentMap *table,
279 const SegmentMap *source_table,
280 MTRandom *rand) {
281 SegmentMap tmp;
282 CHECK_NE(ch.addr1, ch.addr2);
283 CopyChange(ch, &tmp, source_table, rand);
284 Change d(Change::DELETE, ch.size,
285 ch.addr1 < ch.addr2 ? ch.addr1 : ch.addr1 + ch.size);
286 DeleteChange(d, table, &tmp, rand);
287}
288
289void ChangeListMutator::CopyChange(const Change &ch,
290 SegmentMap *table,
291 const SegmentMap *source_table,
292 MTRandom *ignore) {
293 xoff_t m_start = ch.addr2;
294 xoff_t c_start = ch.addr1;
295 xoff_t i_start = 0;
296 xoff_t i_end = 0;
297
298 // Like AddChange() with AppendCopy instead of a random segment.
299 for (SegmentMap::const_iterator iter(source_table->begin());
300 iter != source_table->end();
301 ++iter) {
302 const Segment &seg = iter->second;
303 i_start = iter->first;
304 i_end = i_start + seg.length;
305
306 if (i_end <= m_start) {
307 table->insert(table->end(), make_pair(i_start, seg));
308 continue;
309 }
310
311 if (i_start > m_start) {
312 table->insert(table->end(), make_pair(i_start + ch.size, seg));
313 continue;
314 }
315
316 if (i_start < m_start) {
317 Segment before(seg.seed, m_start - i_start, seg.seed_offset);
318 table->insert(table->end(), make_pair(i_start, before));
319 }
320
321 AppendCopy(table, source_table, c_start, m_start, ch.size);
322
323 if (m_start < i_end) {
324 Segment after(seg.seed, i_end - m_start,
325 seg.seed_offset + (m_start - i_start));
326 table->insert(table->end(), make_pair(m_start + ch.size, after));
327 }
328 }
329
330 CHECK_LE(m_start, i_end);
331
332 // Special case for copy to end-of-input.
333 if (m_start == i_end) {
334 AppendCopy(table, source_table, c_start, m_start, ch.size);
335 }
336}
337
338void ChangeListMutator::AppendCopy(SegmentMap *table,
339 const SegmentMap *source_table,
340 xoff_t copy_offset,
341 xoff_t append_offset,
342 xoff_t length) {
343 SegmentMap::const_iterator pos(source_table->upper_bound(copy_offset));
344 --pos;
345 xoff_t got = 0;
346
347 while (got < length) {
348 size_t seg_offset = copy_offset - pos->first;
349 xoff_t skip = seg_offset + pos->second.seed_offset;
350 size_t advance = min(pos->second.length - seg_offset,
351 (size_t)(length - got));
352
353 table->insert(table->end(),
354 make_pair(append_offset,
355 Segment(pos->second.seed,
356 advance,
357 skip)));
358
359 got += advance;
360 copy_offset += advance;
361 append_offset += advance;
362 ++pos;
363 }
364}
365
261class Modify1stByte : public Mutator { 366class Modify1stByte : public Mutator {
262public: 367public:
263 void Mutate(SegmentMap *table, 368 void Mutate(SegmentMap *table,