monotone

monotone Mtn Source Tree

Root/randomfile.hh

1#ifndef __RANDOMFILE_HH__
2#define __RANDOMFILE_HH__
3
4// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
5//
6// This program is made available under the GNU GPL version 2.0 or
7// greater. See the accompanying file COPYING for details.
8//
9// This program is distributed WITHOUT ANY WARRANTY; without even the
10// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11// PURPOSE.
12
13#include <string>
14#include <vector>
15#include <boost/lexical_cast.hpp>
16
17#include "randomizer.hh"
18
19struct file_randomizer
20{
21 randomizer & rng;
22 std::vector<std::string> lines;
23 std::string prefix;
24
25 file_randomizer(randomizer & rng)
26 : rng(rng)
27 {}
28
29 size_t random_index(bool last_line_ok = true)
30 {
31 if (last_line_ok)
32 return static_cast<size_t>(rng.uniform(lines.size()));
33 else
34 {
35 if (lines.size() == 0)
36 return 0;
37 else
38 return static_cast<size_t>(rng.uniform(lines.size() - 1));
39 }
40 }
41
42 void set_prefix(std::string const & p)
43 {
44 prefix = p;
45 }
46
47 void append_to(std::vector<std::string> & other)
48 {
49 for (std::vector<std::string>::const_iterator i = lines.begin();
50 i != lines.end(); ++i)
51 other.push_back(prefix + *i);
52 }
53
54 void initial_sequential_lines(int num_lines = 100) {
55 lines.clear();
56 for (int i = 0; i < num_lines; ++i)
57 {
58 lines.push_back(std::string("initial ") + boost::lexical_cast<std::string>(i));
59 }
60 }
61
62 void append_sequential_lines(int num_lines = 10) {
63 lines.clear();
64 for (int i = 0; i < num_lines; ++i)
65 {
66 lines.push_back(std::string("append ") + boost::lexical_cast<std::string>(i));
67 }
68 }
69
70 void prepend_sequential_lines(int num_lines = 10) {
71 lines.clear();
72 for (int i = 0; i < num_lines; ++i)
73 {
74 lines.push_back(std::string("prepend ") + boost::lexical_cast<std::string>(i));
75 }
76 }
77
78 void delete_percent_of_lines_randomly(int percent = 50) {
79 double scale = static_cast<double>(percent) / 100.0;
80 double nlines_d = static_cast<double>(lines.size()) * scale;
81 int nlines = static_cast<int>(nlines_d);
82 for (int i = 0; i < nlines; ++i)
83 lines.erase(lines.begin() + random_index(false));
84 }
85
86 void insert_sequential_percent_of_lines_randomly(int percent = 50) {
87 double scale = static_cast<double>(percent) / 100.0;
88 double nlines_d = static_cast<double>(lines.size()) * scale;
89 int nlines = static_cast<int>(nlines_d);
90 for (int i = 0; i < nlines; ++i)
91 {
92 lines.insert(lines.begin() + random_index(),
93 std::string("insert ") + boost::lexical_cast<std::string>(i));
94 }
95 }
96
97 static void build_random_fork(std::vector<std::string> & ancestor,
98 std::vector<std::string> & left,
99 std::vector<std::string> & right,
100 std::vector<std::string> & merged,
101 int n_hunks,
102 randomizer & rng)
103 {
104 bool last_was_insert = false;
105 bool last_insert_was_left = false;
106
107 file_randomizer fr(rng);
108 // maybe prepend something to one side or the other
109 if (rng.flip())
110 {
111 last_was_insert = true;
112 fr.prepend_sequential_lines();
113 last_insert_was_left = rng.flip();
114 if (last_insert_was_left)
115 fr.append_to(left);
116 else
117 fr.append_to(right);
118 fr.append_to(merged);
119 }
120 fr.lines.clear();
121
122 for (int h = 0; h < n_hunks; ++h)
123 {
124 file_randomizer hr(rng);
125 hr.set_prefix(std::string("hunk ") + boost::lexical_cast<std::string>(h) + " -- ");
126 hr.initial_sequential_lines(10);
127 if (rng.flip())
128 {
129 bool this_insert_is_left = rng.flip();
130 if (last_was_insert && (this_insert_is_left != last_insert_was_left))
131 {
132 fr.set_prefix("spacer ");
133 fr.initial_sequential_lines(3);
134 fr.append_to(left);
135 fr.append_to(right);
136 fr.append_to(ancestor);
137 fr.append_to(merged);
138 fr.set_prefix("");
139 }
140 last_insert_was_left = this_insert_is_left;
141 // doing an insert
142 hr.append_to(ancestor);
143 if (this_insert_is_left)
144 {
145 // inserting in left
146 hr.append_to(right);
147 hr.insert_sequential_percent_of_lines_randomly();
148 hr.append_to(left);
149 }
150 else
151 {
152 // inserting in right
153 hr.append_to(left);
154 hr.insert_sequential_percent_of_lines_randomly();
155 hr.append_to(right);
156 }
157 hr.append_to(merged);
158 last_was_insert = true;
159 }
160 else
161 {
162 // doing a delete
163 hr.append_to(ancestor);
164 if (rng.flip())
165 {
166 // deleting in left
167 hr.append_to(right);
168 hr.delete_percent_of_lines_randomly();
169 hr.append_to(left);
170 }
171 else
172 {
173 // deleting in right
174 hr.append_to(left);
175 hr.delete_percent_of_lines_randomly();
176 hr.append_to(right);
177 }
178 hr.append_to(merged);
179 last_was_insert = false;
180 }
181 }
182
183 // maybe append something to one side or the other
184 if (rng.flip())
185 {
186 bool this_insert_is_left = rng.flip();
187 if (last_was_insert && (this_insert_is_left != last_insert_was_left))
188 {
189 fr.set_prefix("spacer ");
190 fr.initial_sequential_lines(3);
191 fr.append_to(left);
192 fr.append_to(right);
193 fr.append_to(ancestor);
194 fr.append_to(merged);
195 fr.set_prefix("");
196 }
197 fr.append_sequential_lines();
198 if (this_insert_is_left)
199 fr.append_to(left);
200 else
201 fr.append_to(right);
202 fr.append_to(merged);
203 }
204 }
205};
206
207// Local Variables:
208// mode: C++
209// fill-column: 76
210// c-file-style: "gnu"
211// indent-tabs-mode: nil
212// End:
213// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
214
215#endif // __RANDOMFILE_HH__

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status