mirror of
https://github.com/nestriness/cdc-file-transfer.git
synced 2026-01-30 16:25:36 +02:00
The tools allow efficient and fast synchronization of large directory trees from a Windows workstation to a Linux target machine. cdc_rsync* support efficient copy of files by using content-defined chunking (CDC) to identify chunks within files that can be reused. asset_stream_manager + cdc_fuse_fs support efficient streaming of a local directory to a remote virtual file system based on FUSE. It also employs CDC to identify and reuse unchanged data chunks.
492 lines
19 KiB
C++
492 lines
19 KiB
C++
// Copyright 2022 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "cdc_rsync/progress_tracker.h"
|
|
|
|
#include <ostream>
|
|
|
|
#include "common/testing_clock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace cdc_ft {
|
|
namespace {
|
|
|
|
// Create custom sizes, so that progress can be easily split up into steps, e.g.
|
|
// kFileSize / 3 + kFileSize / 3, + kFileSize / 3, and the end result is still
|
|
// kFileSize.
|
|
constexpr uint64_t kFileSize = 1 * 2 * 3 * 4 * 5 * 6;
|
|
|
|
// Verbosity.
|
|
const int kV0 = 0;
|
|
const int kV1 = 1;
|
|
|
|
const bool kJson = true;
|
|
const bool kNoJson = false;
|
|
|
|
const bool kQuiet = true;
|
|
const bool kNoQuiet = false;
|
|
|
|
const bool kTTY = true;
|
|
const bool kNoTTY = false;
|
|
|
|
// Class that just creates a list of things it was supposed to print.
|
|
class FakeProgressPrinter : public ProgressPrinter {
|
|
public:
|
|
FakeProgressPrinter(bool quiet, bool is_tty)
|
|
: ProgressPrinter(quiet, is_tty) {}
|
|
|
|
void Print(std::string text, bool newline, int /*output_width*/) override {
|
|
lines_.push_back(text + (newline || !is_tty() ? "\n" : "\r"));
|
|
}
|
|
|
|
void ExpectLinesMatch(std::vector<std::string> expected_lines) {
|
|
EXPECT_EQ(lines_, expected_lines);
|
|
}
|
|
|
|
private:
|
|
std::vector<std::string> lines_;
|
|
};
|
|
|
|
class ProgressTrackerTest : public ::testing::Test {
|
|
protected:
|
|
// Returns the time (in ms) that needs to pass to trigger an output update.
|
|
double GetTriggerPrintTimeDeltaMs(const ProgressTracker& progress) {
|
|
return progress.GetDisplayDelaySecForTesting() * 1000 * 1.5;
|
|
}
|
|
|
|
TestingSteadyClock clock_;
|
|
|
|
uint32_t two_seconds_time_delta_ms_ = 2 * 1000;
|
|
uint32_t two_minutes_time_delta_ms_ = 2 * 60 * 1000;
|
|
uint32_t four_hours_time_delta_ms_ = 4 * 60 * 60 * 1000;
|
|
uint32_t eight_days_time_delta_ms_ = 8 * 24 * 60 * 60 * 1000;
|
|
|
|
const int output_width_ = 66;
|
|
};
|
|
|
|
TEST_F(ProgressTrackerTest, FindFiles) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
progress.StartFindFiles();
|
|
progress.ReportFileFound();
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportFileFound();
|
|
progress.ReportFileFound();
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportFileFound();
|
|
progress.ReportFileFound();
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch({"2 file(s) and 0 folder(s) found\r",
|
|
"4 file(s) and 0 folder(s) found\r",
|
|
"5 file(s) and 0 folder(s) found\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, FindFilesVerbose) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV1, kNoJson, output_width_, &clock_);
|
|
|
|
progress.StartFindFiles();
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportFileFound();
|
|
progress.Finish();
|
|
|
|
// Find files should be the same as non-verbose.
|
|
printer.ExpectLinesMatch({"1 file(s) and 0 folder(s) found\r",
|
|
"1 file(s) and 0 folder(s) found\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, CopyFiles) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch({"100% TOT 00:00 \r", "100% TOT 00:00 \n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, CopyFilesVerbose) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV1, kNoJson, output_width_, &clock_);
|
|
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{"file.txt C 66% 720B 3.1KB/s 00:00 ETA 100% TOT 00:00 \r",
|
|
"file.txt C100% 720B 4.7KB/s 00:00 100% TOT 00:00 \n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, SyncFiles) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
// 1 changed file.
|
|
progress.ReportFileStats(0, 0, 0, 1, 0, kFileSize, kFileSize, 0, 0, 0);
|
|
|
|
progress.StartSync("file.txt", kFileSize, kFileSize);
|
|
progress.ReportSyncProgress(0, kFileSize / 2);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportSyncProgress(0, kFileSize / 2);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportSyncProgress(kFileSize / 3, 0);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportSyncProgress(kFileSize / 3, 0);
|
|
progress.ReportSyncProgress(kFileSize / 3, 0);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 1 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n",
|
|
" 2% TOT 00:05 ETA\r", " 34% TOT 00:00 ETA\r", " 67% TOT 00:00 ETA\r",
|
|
"100% TOT 00:00 \n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, SyncFilesVerbose) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV1, kNoJson, output_width_, &clock_);
|
|
|
|
// 1 changed file.
|
|
progress.ReportFileStats(0, 0, 0, 1, 0, kFileSize, kFileSize, 0, 0, 0);
|
|
|
|
progress.StartSync("file.txt", kFileSize, kFileSize);
|
|
clock_.Advance(two_seconds_time_delta_ms_);
|
|
progress.ReportSyncProgress(0, kFileSize / 3);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportSyncProgress(kFileSize / 3, 0);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportSyncProgress(0, kFileSize / 3);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportSyncProgress(0, kFileSize / 3);
|
|
progress.ReportSyncProgress(kFileSize / 3, 0);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportSyncProgress(kFileSize / 3, 0);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 1 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n",
|
|
"file.txt S 0% 720B ---.-B /s 04:03 ETA 0% TOT 04:03 ETA\r",
|
|
"file.txt D 33% 720B 117.1B /s 00:04 ETA 33% TOT 00:04 ETA\r",
|
|
"file.txt S 34% 720B ---.-B /s 00:04 ETA 34% TOT 00:04 ETA\r",
|
|
"file.txt S 34% 720B ---.-B /s 00:04 ETA 34% TOT 00:04 ETA\r",
|
|
"file.txt D100% 720B 276.9B /s 00:02 100% TOT 00:02 \r",
|
|
"file.txt D100% 720B 276.9B /s 00:02 100% TOT 00:02 \n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, DeleteFiles) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
// 2 extraneous files.
|
|
progress.ReportFileStats(0, 4, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
progress.StartDeleteFiles();
|
|
progress.ReportFileDeleted("file1.txt");
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportFileDeleted("file2.txt");
|
|
progress.ReportFileDeleted("file3.txt");
|
|
progress.ReportFileDeleted("file4.txt");
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 0 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 4 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n",
|
|
"2/4 file(s) and 0/0 folder(s) deleted.\r",
|
|
"4/4 file(s) and 0/0 folder(s) deleted.\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, DeleteFilesVerbose) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV1, kNoJson, output_width_, &clock_);
|
|
|
|
// 2 extraneous files.
|
|
progress.ReportFileStats(0, 2, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
progress.StartDeleteFiles();
|
|
progress.ReportFileDeleted("file1.txt");
|
|
progress.ReportFileDeleted("file2.txt");
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 0 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 2 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n",
|
|
"file1.txt deleted 1 / 2\n",
|
|
"file2.txt deleted 2 / 2\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, DeleteFilesNoFiles) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
progress.ReportFileStats(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
progress.StartDeleteFiles();
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 0 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, SetFileStatsAndUnits) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV1, kNoJson, output_width_, &clock_);
|
|
|
|
// Have a very large file and trigger different ETAs and transfer speeds.
|
|
constexpr uint64_t large_file_size = 2ull * 1024 * 1024 * 1024 * 1024;
|
|
progress.ReportFileStats(1, 0, 0, 0, large_file_size, 0, 0, 0, 0, 0);
|
|
|
|
progress.StartCopy("file.txt", large_file_size);
|
|
progress.ReportCopyProgress(large_file_size / 4);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(large_file_size / 4);
|
|
clock_.Advance(two_seconds_time_delta_ms_);
|
|
progress.ReportCopyProgress(large_file_size / 4);
|
|
clock_.Advance(two_minutes_time_delta_ms_);
|
|
progress.ReportCopyProgress(large_file_size / 8);
|
|
clock_.Advance(four_hours_time_delta_ms_);
|
|
progress.ReportCopyProgress(large_file_size / 8);
|
|
clock_.Advance(eight_days_time_delta_ms_);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 1 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 0 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n",
|
|
"file.txt C 50% 2048GB 6.7TB/s 00:00 ETA 50% TOT 00:00 ETA\r",
|
|
"file.txt C 75% 2048GB 714.4GB/s 00:00 ETA 75% TOT 00:00 ETA\r",
|
|
"file.txt C 87% 2048GB 14.7GB/s 00:17 ETA 87% TOT 00:17 ETA\r",
|
|
"file.txt C100% 2048GB 144.4MB/s 04:02:02 100% TOT 04:02:02 "
|
|
"\r",
|
|
"file.txt C100% 2048GB 3.0MB/s 196:02:02 100% TOT 196:02:02 "
|
|
" \n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, QuietMode) {
|
|
FakeProgressPrinter printer(kQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV1, kNoJson, output_width_, &clock_);
|
|
|
|
progress.StartFindFiles();
|
|
progress.ReportFileFound();
|
|
progress.Finish();
|
|
|
|
// 1 missing, 1 extraneous, and 1 changed files
|
|
// 1 extraneous folder
|
|
progress.ReportFileStats(1, 1, 1, 0, kFileSize, kFileSize, kFileSize, 0, 0,
|
|
1);
|
|
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
progress.ReportCopyProgress(kFileSize);
|
|
progress.Finish();
|
|
|
|
progress.StartSync("file.txt", kFileSize, kFileSize);
|
|
progress.ReportSyncProgress(kFileSize, kFileSize);
|
|
progress.Finish();
|
|
|
|
progress.StartDeleteFiles();
|
|
progress.ReportFileDeleted("file.txt");
|
|
progress.ReportDirDeleted("folder");
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch({});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, NoTTY) {
|
|
FakeProgressPrinter tty_printer(kNoQuiet, kTTY);
|
|
ProgressTracker tty_progress(&tty_printer, kV1, kNoJson, output_width_,
|
|
&clock_);
|
|
double tty_delta_ms = GetTriggerPrintTimeDeltaMs(tty_progress);
|
|
|
|
// In no-TTY-mode (e.g. cdc_rsync .. > out.txt), the display rate should be
|
|
// lower (currently every 1 second instead of 0.1 seconds).
|
|
FakeProgressPrinter printer(kNoQuiet, kNoTTY);
|
|
ProgressTracker progress(&printer, kV1, kNoJson, output_width_, &clock_);
|
|
EXPECT_GT(GetTriggerPrintTimeDeltaMs(progress), tty_delta_ms);
|
|
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{"file.txt C 33% 720B 160.0B /s 00:03 ETA 100% TOT 00:01 \n",
|
|
"file.txt C 66% 720B 160.0B /s 00:01 ETA 100% TOT 00:03 \n",
|
|
"file.txt C100% 720B 240.0B /s 00:03 100% TOT 00:03 \n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, JsonPerFile) {
|
|
FakeProgressPrinter printer(kNoQuiet, kNoTTY);
|
|
ProgressTracker progress(&printer, kV1, kJson, output_width_, &clock_);
|
|
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{"{\"bytes_per_second\":160.0,\"duration\":1.5,\"eta\":3.0,\"file\":"
|
|
"\"file.txt\",\"operation\":\"Copy\",\"size\":720,\"total_duration\":1."
|
|
"5,\"total_eta\":0.0,\"total_progress\":1.0}\n",
|
|
"{\"bytes_per_second\":160.0,\"duration\":3.0,\"eta\":1.5,\"file\":"
|
|
"\"file.txt\",\"operation\":\"Copy\",\"size\":720,\"total_duration\":3."
|
|
"0,\"total_eta\":0.0,\"total_progress\":1.0}\n",
|
|
"{\"bytes_per_second\":240.0,\"duration\":3.0,\"eta\":0.0,\"file\":"
|
|
"\"file.txt\",\"operation\":\"Copy\",\"size\":720,\"total_duration\":3."
|
|
"0,\"total_eta\":0.0,\"total_progress\":1.0}\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, JsonTotal) {
|
|
FakeProgressPrinter printer(kNoQuiet, kNoTTY);
|
|
ProgressTracker progress(&printer, kV0, kJson, output_width_, &clock_);
|
|
|
|
progress.ReportFileStats(0, 0, 0, 1, 0, kFileSize, kFileSize, 0, 0, 0);
|
|
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
clock_.Advance(GetTriggerPrintTimeDeltaMs(progress));
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.ReportCopyProgress(kFileSize / 3);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 1 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n",
|
|
"{\"total_duration\":1.5,\"total_eta\":3.1124999999999998,\"total_"
|
|
"progress\":0.32520325203252032}\n",
|
|
"{\"total_duration\":3.0,\"total_eta\":1.6124999999999998,\"total_"
|
|
"progress\":0.65040650406504064}\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, SyncFilesWithWholeFile) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
// 1 changed file with -W arg.
|
|
progress.ReportFileStats(0, 0, 0, 1, 0, kFileSize, kFileSize, 0, 0, 0, true);
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 1 file(s) changed and will be copied due to -W/--whole-file.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, SyncFilesWithChecksum) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
// 1 matching file with -c arg.
|
|
progress.ReportFileStats(0, 0, 1, 0, 0, kFileSize, kFileSize, 0, 0, 0, false,
|
|
true);
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 0 file(s) changed and will be updated.\n",
|
|
" 1 file(s) and 0 folder(s) have matching modified time and size, "
|
|
"but will be synced due to -c/--checksum.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, SyncFilesWithChecksumAndWholeFile) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
// 1 changed file, 1 matching file. with -c and -W args.
|
|
progress.ReportFileStats(0, 0, 1, 1, 0, kFileSize, kFileSize, 0, 0, 0, true,
|
|
true);
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 1 file(s) changed and will be copied due to -W/--whole-file.\n",
|
|
" 1 file(s) and 0 folder(s) have matching modified time and size, "
|
|
"but will be copied due to -c/--checksum and -W/--whole-file.\n",
|
|
" 0 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine.\n"});
|
|
}
|
|
|
|
TEST_F(ProgressTrackerTest, SyncFilesWithDelete) {
|
|
FakeProgressPrinter printer(kNoQuiet, kTTY);
|
|
ProgressTracker progress(&printer, kV0, kNoJson, output_width_, &clock_);
|
|
|
|
// 1 extraneous file with --delete arg.
|
|
progress.ReportFileStats(0, 1, 0, 0, 0, kFileSize, kFileSize, 0, 0, 0, false,
|
|
false, true);
|
|
progress.StartCopy("file.txt", kFileSize);
|
|
progress.Finish();
|
|
|
|
printer.ExpectLinesMatch(
|
|
{" 0 file(s) and 0 folder(s) are not present on the instance and "
|
|
"will be copied.\n",
|
|
" 0 file(s) changed and will be updated.\n",
|
|
" 0 file(s) and 0 folder(s) match and do not have to be updated.\n",
|
|
" 1 file(s) and 0 folder(s) on the instance do not exist on this "
|
|
"machine and will be deleted due to --delete.\n"});
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace cdc_ft
|