return NULL;
}
-/** Apply the ed diff to the consensus and return a new consensus, also as a
- * line-based smartlist. Will return NULL if the ed diff is not properly
- * formatted.
+/** Apply the ed diff, starting at <b>diff_starting_line</b>, to the consensus
+ * and return a new consensus, also as a line-based smartlist. Will return
+ * NULL if the ed diff is not properly formatted.
*/
STATIC smartlist_t *
-apply_ed_diff(const smartlist_t *cons1, const smartlist_t *diff)
+apply_ed_diff(const smartlist_t *cons1, const smartlist_t *diff,
+ int diff_starting_line)
{
int diff_len = smartlist_len(diff);
int j = smartlist_len(cons1);
smartlist_t *cons2 = smartlist_new();
- for (int i=0; i<diff_len; ++i) {
+ for (int i=diff_starting_line; i<diff_len; ++i) {
const char *diff_line = smartlist_get(diff, i);
char *endptr1, *endptr2;
}
/* See that the script actually produces what we want. */
- smartlist_t *ed_cons2 = apply_ed_diff(cons1, ed_diff);
+ smartlist_t *ed_cons2 = apply_ed_diff(cons1, ed_diff, 0);
if (!ed_cons2) {
/* LCOV_EXCL_START -- impossible if diff generation is correct */
log_warn(LD_BUG|LD_CONSDIFF, "Refusing to generate consensus diff because "
}
/* Grab the ed diff and calculate the resulting consensus. */
- /* To avoid copying memory or iterating over all the elements, make a
- * read-only smartlist without the two header lines.
- */
- /* XXXX prop140 abstraction violation; never do this. */
- smartlist_t *ed_diff = tor_malloc(sizeof(smartlist_t));
- ed_diff->list = diff->list+2;
- ed_diff->num_used = diff->num_used-2;
- ed_diff->capacity = diff->capacity-2;
- cons2 = apply_ed_diff(cons1, ed_diff);
- tor_free(ed_diff);
+ /* Skip the first two lines. */
+ cons2 = apply_ed_diff(cons1, diff, 2);
/* ed diff could not be applied - reason already logged by apply_ed_diff. */
if (!cons2) {
/* Command without range. */
smartlist_add(diff, (char*)"a");
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
smartlist_clear(diff);
expect_single_log_msg_containing("an ed command was missing a line number");
/* Range without command. */
smartlist_add(diff, (char*)"1");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("a line with no ed command was found");
/* Range without end. */
smartlist_add(diff, (char*)"1,");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("an ed command was missing a range "
"end line number.");
/* Incoherent ranges. */
smartlist_add(diff, (char*)"1,1");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("an invalid range was found");
smartlist_add(diff, (char*)"3,2");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("an invalid range was found");
smartlist_add(diff, (char*)"1d");
smartlist_add(diff, (char*)"3d");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("its commands are not properly sorted");
/* Script contains unrecognised commands longer than one char. */
smartlist_add(diff, (char*)"1foo");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("an ed command longer than one char was "
"found");
/* Script contains unrecognised commands. */
smartlist_add(diff, (char*)"1e");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("an unrecognised ed command was found");
* isn't. */
smartlist_add(diff, (char*)"0a");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("it has an ed command that tries to "
"insert zero lines.");
/* Now it is followed by a ".", but it inserts zero lines. */
smartlist_add(diff, (char*)".");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("it has an ed command that tries to "
"insert zero lines.");
smartlist_add(diff, (char*)"0a");
smartlist_add(diff, (char*)"hello");
mock_clean_saved_logs();
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_EQ, cons2);
expect_single_log_msg_containing("lines to be inserted that don't end with "
"a \".\".");
/* Test appending text, 'a'. */
smartlist_split_string(diff, "3a:U:O:.:0a:V:.", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(8, OP_EQ, smartlist_len(cons2));
tt_str_op("V", OP_EQ, smartlist_get(cons2, 0));
/* Test deleting text, 'd'. */
smartlist_split_string(diff, "4d:1,2d", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(2, OP_EQ, smartlist_len(cons2));
tt_str_op("C", OP_EQ, smartlist_get(cons2, 0));
/* Test changing text, 'c'. */
smartlist_split_string(diff, "4c:T:X:.:1, 2c:M:.", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(5, OP_EQ, smartlist_len(cons2));
tt_str_op("M", OP_EQ, smartlist_get(cons2, 0));
/* Test 'a', 'd' and 'c' together. */
smartlist_split_string(diff, "4c:T:X:.:2d:0a:M:.", ":", 0, 0);
- cons2 = apply_ed_diff(cons1, diff);
+ cons2 = apply_ed_diff(cons1, diff, 0);
tt_ptr_op(NULL, OP_NE, cons2);
tt_int_op(6, OP_EQ, smartlist_len(cons2));
tt_str_op("M", OP_EQ, smartlist_get(cons2, 0));