fix(parity): rsync bwlimit units, --info categories, --ignore-errors deletion semantics
- --bwlimit: faithful port of rsync 3.4.1 parse_size_arg (default KiB/s, binary K/M/G/T/P, decimal KB/MB, KiB/MiB, decimals, 0 = unlimited, 512-byte floor, (size+512)/1024 quantization). Unit tests + docs. - --info: wire del/remove/name/flist/nonreg/progress to real FastSync events in rsync's line format (deleting PATH, sender removed NAME, name lines, 'sending incremental file list', skipping non-regular file "NAME"); name no longer aliases copy; --info=progress drives the progress path and report_stats. - --ignore-errors: match rsync's default -- a source I/O error skips deletion unless --ignore-errors, while the readable tree still transfers and the run exits 23. Covers all delete timings and both send paths.
This commit is contained in:
+68
-5
@@ -7,6 +7,7 @@
|
||||
#include "delta.h"
|
||||
#include "file_list.h"
|
||||
#include "log.h"
|
||||
#include "protocol.h"
|
||||
#include "test_utils.h"
|
||||
#include "utils.h"
|
||||
#include <pwd.h>
|
||||
@@ -1327,7 +1328,7 @@ static void test_parse_args_rejects_invalid_info_flag() {
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
/* rsync's info "name" category maps to fastsync's per-file name logging, and
|
||||
/* rsync's info "name" category maps to fastsync's per-file name output, and
|
||||
* --info=help prints the flag list and exits without error. */
|
||||
static void test_parse_args_info_name_and_help() {
|
||||
Config* cfg = config_create();
|
||||
@@ -1335,7 +1336,7 @@ static void test_parse_args_info_name_and_help() {
|
||||
int positional_args[2];
|
||||
int positional_count = 0;
|
||||
EXPECT_EQ_INT(parse_args(cfg, 4, argv, positional_args, &positional_count), 0);
|
||||
EXPECT_EQ_INT(cfg->info_level, LOG_INFO_COPY);
|
||||
EXPECT_EQ_INT(cfg->info_level, LOG_INFO_NAME);
|
||||
config_delete(cfg);
|
||||
|
||||
cfg = config_create();
|
||||
@@ -1345,8 +1346,10 @@ static void test_parse_args_info_name_and_help() {
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
/* rsync 3.4.1's remaining --info/--debug categories parse successfully but
|
||||
* have no FastSync output wired to them, so they must not set any log flag. */
|
||||
/* rsync 3.4.1's full --info/--debug vocabulary parses. The info categories
|
||||
* with a FastSync event set their flag; the remaining rsync-only categories
|
||||
* (mount/symsafe/syms) parse but stay silent. Every --debug category listed
|
||||
* here is FastSync-silent, so debug_level stays 0. */
|
||||
static void test_parse_args_rsync_flag_vocabulary_accepted() {
|
||||
Config* cfg = config_create();
|
||||
char* argv[] = {"fastsync", "--info=backup,del,flist,mount,nonreg,progress,remove,symsafe,syms",
|
||||
@@ -1358,7 +1361,8 @@ static void test_parse_args_rsync_flag_vocabulary_accepted() {
|
||||
int positional_count = 0;
|
||||
|
||||
EXPECT_EQ_INT(parse_args(cfg, 4, argv, positional_args, &positional_count), 0);
|
||||
EXPECT_EQ_INT(cfg->info_level, 0);
|
||||
EXPECT_EQ_INT(cfg->info_level, LOG_INFO_BACKUP | LOG_INFO_DEL | LOG_INFO_FLIST |
|
||||
LOG_INFO_NONREG | LOG_INFO_PROGRESS | LOG_INFO_REMOVE);
|
||||
EXPECT_EQ_INT(cfg->debug_level, 0);
|
||||
config_delete(cfg);
|
||||
}
|
||||
@@ -3870,6 +3874,64 @@ static void test_parse_args_unsigned_options_reject_sign() {
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
/* --bwlimit must parse with rsync 3.4.1's units and quantization: a bare value
|
||||
* is KiB/s, K/M/G/T/P are binary multipliers, KB/MB are decimal, KiB/MiB are
|
||||
* binary, decimals are rounded to whole KiB like rsync's (size + 512) / 1024,
|
||||
* and 0 (or an empty value) means "no limit". */
|
||||
static void test_parse_args_bwlimit_rsync_units() {
|
||||
struct {
|
||||
const char* value;
|
||||
unsigned long long expected; /* bytes/sec */
|
||||
int ok;
|
||||
} cases[] = {
|
||||
{"100", 100ULL * 1024, 1},
|
||||
{"0", 0, 1},
|
||||
{"", 0, 1},
|
||||
{"1.5", 2ULL * 1024, 1},
|
||||
{"100K", 100ULL * 1024, 1},
|
||||
{"100KiB", 100ULL * 1024, 1},
|
||||
{"100KB", (100000ULL + 512) / 1024 * 1024, 1},
|
||||
{"1M", 1024ULL * 1024, 1},
|
||||
{"1MB", (1000000ULL + 512) / 1024 * 1024, 1},
|
||||
{"1.5m", 1536ULL * 1024, 1},
|
||||
{"1G", 1024ULL * 1024 * 1024, 1},
|
||||
{"1000B", (1000ULL + 512) / 1024 * 1024, 1},
|
||||
{"100B", 0, 0}, /* below the 512-byte floor (not 0) */
|
||||
{"0.4", 0, 0}, /* 409 bytes, below the floor */
|
||||
{"511", 511ULL * 1024, 1},
|
||||
{"-1", 0, 0},
|
||||
{"abc", 0, 0},
|
||||
{"1x", 0, 0},
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
Config* cfg = config_create();
|
||||
EXPECT_NOT_NULL(cfg);
|
||||
int positional_args[2];
|
||||
int positional_count = 0;
|
||||
char option[32];
|
||||
snprintf(option, sizeof(option), "--bwlimit=%s", cases[i].value);
|
||||
char* argv[] = {"fastsync", option, "/src", "/dst"};
|
||||
int rc = parse_args(cfg, 4, argv, positional_args, &positional_count);
|
||||
if (cases[i].ok) {
|
||||
EXPECT_EQ_INT(rc, 0);
|
||||
EXPECT_TRUE(io_get_bwlimit() == cases[i].expected);
|
||||
} else {
|
||||
EXPECT_EQ_INT(rc, -1);
|
||||
}
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
Config* cfg = config_create();
|
||||
EXPECT_NOT_NULL(cfg);
|
||||
int positional_args[2];
|
||||
int positional_count = 0;
|
||||
char* argv[] = {"fastsync", "--bwlimit", "512", "/src", "/dst"};
|
||||
EXPECT_EQ_INT(parse_args(cfg, 5, argv, positional_args, &positional_count), 0);
|
||||
EXPECT_TRUE(io_get_bwlimit() == 512ULL * 1024);
|
||||
config_delete(cfg);
|
||||
io_set_bwlimit(0);
|
||||
}
|
||||
|
||||
/* --dry-run must not emit a batch file, so it is rejected alongside
|
||||
* --read-batch/--only-write-batch. */
|
||||
static void test_validate_config_dry_run_rejects_write_batch() {
|
||||
@@ -4579,6 +4641,7 @@ void test_client_cli() {
|
||||
test_parse_args_password_file();
|
||||
test_parse_args_pattern_file_oversized_rejected();
|
||||
test_parse_args_unsigned_options_reject_sign();
|
||||
test_parse_args_bwlimit_rsync_units();
|
||||
test_validate_config_dry_run_rejects_write_batch();
|
||||
test_parse_args_short_clustering();
|
||||
test_parse_args_attached_short_values();
|
||||
|
||||
Reference in New Issue
Block a user