// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Security.Cryptography; using System.Data; namespace Spludlow.Io { public class DiskTest { public static void TestWrite(string[] volumes) { int passCount = 1; int fileSizeMeg = 16; DataTable table = Spludlow.Data.TextTable.ReadText(new string[] { "Volume Action Pass Time Took Result", "String String Int32 DateTime String String", }); Task[] tasks = new Task[volumes.Length]; for (int index = 0; index < volumes.Length; ++index) { string volume = volumes[index]; tasks[index] = new Task(() => TestWriteWorker(volume, passCount, fileSizeMeg, table)); } for (int index = 0; index < tasks.Length; ++index) { if (index > 0) System.Threading.Thread.Sleep(1000); // Prevent format getting duplicate Volume Serial Number tasks[index].Start(); } Task.WaitAll(tasks); Spludlow.Log.Report("Disk Test Write", table); } public static void TestWriteWorker(string volume, int passCount, int fileSizeMeg, DataTable table) { string label = "TEST_" + volume[0]; DateTime last; bool error = false; for (int pass = 0; pass < passCount; ++pass) { string result; last = DateTime.Now; try { result = Spludlow.Io.Format.FormatDisk(volume, null, label); } catch (Exception e) { result = e.Message; error = true; } lock (table) { table.Rows.Add(volume, "FORMAT", pass, DateTime.Now, Spludlow.Text.TimeTook(last), result); } if (error == true) break; last = DateTime.Now; try { result = FillRandom(volume + @"\", fileSizeMeg).ToString(); } catch (Exception e) { result = e.Message; error = true; } lock (table) { table.Rows.Add(volume, "WRITE", pass, DateTime.Now, Spludlow.Text.TimeTook(last), result); } if (error == true) break; } } public static int FillRandom(string directory, int sizeMeg) { Random random = new Random(); byte[] buffer = new byte[1024 * 1024]; int count = 0; while (true) { SHA1 hash = new SHA1Managed(); using (MemoryStream memoryStream = new MemoryStream()) { using (CryptoStream cryStream = new CryptoStream(memoryStream, hash, CryptoStreamMode.Write)) { for (int meg = 0; meg < sizeMeg; ++meg) { random.NextBytes(buffer); cryStream.Write(buffer, 0, buffer.Length); } cryStream.FlushFinalBlock(); } string filename = directory + @"\" + Spludlow.Hashing.Hex(hash.Hash); try { File.WriteAllBytes(filename, memoryStream.ToArray()); ++count; } catch (IOException ee) { if ((uint)ee.HResult != 0x80070070) throw ee; File.Delete(filename); break; } } } return count; } public static void TestRead(string[] volumes) { int passCount = 1; int fileSizeMeg = 16; DataTable table = Spludlow.Data.TextTable.ReadText(new string[] { "Volume Action Pass Time Took Result", "String String Int32 DateTime String String", }); Task[] tasks = new Task[volumes.Length]; for (int index = 0; index < volumes.Length; ++index) { string volume = volumes[index]; tasks[index] = new Task(() => TestReadWorker(volume, passCount, fileSizeMeg, table)); } foreach (Task task in tasks) task.Start(); Task.WaitAll(tasks); Spludlow.Log.Report("Disk Test Read", table); } public static void TestReadWorker(string volume, int passCount, int fileSizeMeg, DataTable table) { DateTime last; bool error = false; for (int pass = 0; pass < passCount; ++pass) { string result; last = DateTime.Now; try { result = ReadRandom(volume + @"\"); } catch (Exception e) { result = e.Message; error = true; } lock (table) { table.Rows.Add(volume, "READ", pass, DateTime.Now, Spludlow.Text.TimeTook(last), result); } if (error == true) break; } } public static string ReadRandom(string directory) { string[] filenames = Directory.GetFiles(directory); int count = 0; foreach (string filename in filenames) { byte[] data = File.ReadAllBytes(filename); if (Spludlow.Hashing.SHA1Hex(data) != Path.GetFileName(filename)) break; ++count; } if (count == filenames.Length) return count.ToString(); return count + "/" + filenames.Length; } } }