<commit_before>﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BackyLogic;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;

namespace TestBacky
{
    [TestClass]
    public class TestRunBackupCommand
    {
        [TestMethod, Ignore]
        public void Test00_Playing_around()
        {
            var files1 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
            var files2 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
            var files3 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
            var files4 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
        }

        [TestMethod, Ignore]
        public void Test00_1_Running_on_real_file_system()
        {
            var source = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));
            var target = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));

            // Clear target
            if (Directory.Exists(target)) // This method sometimes return true when the directory doesn't realy exists
                Directory.Delete(target, true);
            Directory.CreateDirectory(target);

            // Clear source
            if (Directory.Exists(source))
                Directory.Delete(source, true);
            Directory.CreateDirectory(source);


            var cmd = new RunBackupCommand(new FileSystem(), source, target);

            // Create files in source and run first time
            File.WriteAllText(Path.Combine(source, "file1.txt"), "hello1");
            File.WriteAllText(Path.Combine(source, "file2.txt"), "hello2");
            File.WriteAllText(Path.Combine(source, "file3.txt"), "hello3");
            File.WriteAllText(Path.Combine(source, "file4.doc"), "");

            // 1
            cmd.Execute();

            // Add new files
            File.WriteAllText(Path.Combine(source, "file5.txt"), "hello5");
            File.WriteAllText(Path.Combine(source, "file6.txt"), "hello6");

            // 2
            cmd.Execute();

            // Delete a few files
            File.Delete(Path.Combine(source, "file1.txt"));
            File.Delete(Path.Combine(source, "file2.txt"));

            // 3
            cmd.Execute();

            // Modify and add some files
            File.WriteAllText(Path.Combine(source, "file5.txt"), "hello5 - modified");
            File.WriteAllText(Path.Combine(source, "file6.txt"), "hello6 - modified");
            File.WriteAllText(Path.Combine(source, "file7.txt"), "hello7");

            // 4
            cmd.Execute();

            // Assertion
            var actualTargetFiles = Directory.GetFiles(target, "*", SearchOption.AllDirectories);
            var expectedTargetFiles = new[]
                { "1\\new\\file1.txt", "1\\new\\file2.txt", "1\\new\\file3.txt", "1\\new\\file4.doc",
                  "2\\new\\file5.txt", "2\\new\\file6.txt",
                  "3\\deleted.txt",
                  "4\\modified\\file5.txt", "4\\modified\\file6.txt", "4\\new\\file7.txt"
            }.Select(x => Path.Combine(target, x));
            AssertLists(expectedTargetFiles, actualTargetFiles);

            var expectedDeleted = new[] { "file1.txt", "file2.txt" };
            var actualDeleted = File.ReadAllLines(Path.Combine(target, "3", "deleted.txt"));
            AssertLists(expectedDeleted, actualDeleted);

            Directory.Delete(target, true);
            Directory.Delete(source, true);
        }

        [TestMethod]
        public void Test01_Running_for_the_first_time()
        {
            // This test simulate running the tool for the first time.
            // We only have files under the source directory
            // After running the tool, we expect to see all files from the source copied into
            // the target location under %target%/1/new

            var source = @"c:\source";<commit_msg>added real file system test for renamed files<commit_after>﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BackyLogic;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Security.AccessControl;

namespace TestBacky
{
    [TestClass]
    public class TestRunBackupCommand
    {
        [TestMethod, Ignore]
        public void Test00_Playing_around()
        {
            var files1 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
            var files2 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
            var files3 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
            var files4 = Directory.GetFiles(@"D:\DataFromExternalDrive", "*.*", SearchOption.AllDirectories);
        }

        [TestMethod]
        public void Test01_Running_on_a_real_file_system()
        {
            var source = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));
            var target = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));

            // Clear target
            if (Directory.Exists(target)) // This method sometimes return true when the directory doesn't realy exists
                Directory.Delete(target, true);
            Directory.CreateDirectory(target);

            // Clear source
            if (Directory.Exists(source))
                Directory.Delete(source, true);
            Directory.CreateDirectory(source);


            var cmd = new RunBackupCommand(new FileSystem(), source, target);

            // Create files in source and run first time
            File.WriteAllText(Path.Combine(source, "file1.txt"), "hello1");
            File.WriteAllText(Path.Combine(source, "file2.txt"), "hello2");
            File.WriteAllText(Path.Combine(source, "file3.txt"), "hello3");
            File.WriteAllText(Path.Combine(source, "file4.doc"), "");

            // 1
            cmd.Execute();

            // Add new files
            File.WriteAllText(Path.Combine(source, "file5.txt"), "hello5");
            File.WriteAllText(Path.Combine(source, "file6.txt"), "hello6");

            // 2
            cmd.Execute();

            // Delete a few files
            File.Delete(Path.Combine(source, "file1.txt"));
            File.Delete(Path.Combine(source, "file2.txt"));

            // 3
            cmd.Execute();

            // Modify and add some files
            File.WriteAllText(Path.Combine(source, "file5.txt"), "hello5 - modified");
            File.WriteAllText(Path.Combine(source, "file6.txt"), "hello6 - modified");
            File.WriteAllText(Path.Combine(source, "file7.txt"), "hello7");

            // 4
            cmd.Execute();

            // Rename some files
            File.Move(Path.Combine(source, "file5.txt"), Path.Combine(source, "file5_renamed.txt"));
            Directory.CreateDirectory(Path.Combine(source, "subdir"));
            File.Move(Path.Combine(source, "file6.txt"), Path.Combine(source, "subdir", "file6_renamed.txt"));

            // 5
            cmd.Execute();

            // Assert existence of files according to structure
            var actualTargetFiles = Directory.GetFiles(target, "*", SearchOption.AllDirectories);
            var expectedTargetFiles = new[]
                { "1\\new\\file1.txt", "1\\new\\file2.txt", "1\\new\\file3.txt", "1\\new\\file4.doc",
                  "2\\new\\file5.txt", "2\\new\\file6.txt",
                  "3\\deleted.txt",
                  "4\\modified\\file5.txt", "4\\modified\\file6.txt", "4\\new\\file7.txt",
                  "5\\renamed.txt"
            }.Select(x => Path.Combine(target, x));
            AssertLists(expectedTargetFiles, actualTargetFiles);

            // Assert deleted file are marked correctly
            var expectedDeleted = new[] { "file1.txt", "file2.txt" };
            var actualDeleted = File.ReadAllLines(Path.Combine(target, "3", "deleted.txt"));
            AssertLists(expectedDeleted, actualDeleted);

            // Assert renamed files are marked correctly
            var renamedFiles = File.ReadAllLines(Path.Combine(target, "5", "renamed.txt"))
                .Select(JObject.Parse)
                .Select(x => new
                {
                    oldName = x.Value<string>("oldName"),
                    newName = x.Value<string>("newName")
                }).ToArray();

            Assert.AreEqual(2, renamedFiles.Length);
            Assert.AreEqual("file5.txt", renamedFiles[0].oldName);
            Assert.AreEqual("file5_renamed.txt", renamedFiles[0].newName);
            Assert.AreEqual("file6.txt", renamedFiles[1].oldName);
            Assert.AreEqual("subdir\\file6_renamed.txt", renamedFiles[1].newName);

            foreach (var dir in Directory.GetDirectories(target))
                UnmarkDirectoryAsReadOnly(dir);
            Directory.Delete(target, true);
            Directory.Delete(source, true);
        }

        private void UnmarkDirectoryAsReadOnly(string dirName)
        {
            DirectoryInfo dInfo = new DirectoryInfo(dirName);
            DirectorySecurity dSecurity = dInfo.GetAccessControl();
            dSecurity.SetAccessRuleProtection(true, false); // Disable inheritance
            dSecurity.AddAccessRule(
                new FileSystemAccessRule(
                    "Everyone",
                    FileSystemRights.FullControl,
                    InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,
                    PropagationFlags.None, AccessControlType.Allow));
            dInfo.SetAccessControl(dSecurity);
        }

        [TestMethod]
        public void Test01_Running_for_the_first_time()
        {
            // This test simulate running the tool for the first time.
            // We only have files under the source directory
            // After running the tool, we expect to see all files from the source copied into
            // the target location under %target%/1/new

            var source = @"c:\source";
{'fraction_non_alphanumeric': 0.1263635486050777, 'fraction_numerical': 0.012452939472922097, 'mean_word_length': 2.1867117809904646, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4019347', 'n_tokens_mistral': 2880, 'n_tokens_neox': 2756, 'n_words': 560}