1 module test_md5;
2 
3 /** MD5 Checksum Routines Unittest (D module) */
4 import core.stdc.stdlib;
5 import std.datetime.stopwatch;
6 import std.digest;
7 import std.digest.md;
8 import std.file;
9 import std.format;
10 import std.range;
11 import std.stdint;
12 import std.stdio;
13 
14 import test_helpers;
15 import test_csv;
16 
17 /** Test and benchmark the MD5 functions */
18 
19 int test_md5(int argTimeLimit, bool writeCSV) {
20 	auto csvFileName = "./docs/benchmark_md5.csv";
21 	auto csvFile = new TestCSVFile!MD5TestData(csvFileName);
22 
23 	auto timeLimitSW = StopWatch(AutoStart.yes);
24 	auto sw = StopWatch(AutoStart.no);
25 	const int rc = 0;
26 	float mbs_average = 0.0;
27 	int mbs_counts = 0;
28 
29 	outerloop: foreach (int size; 4 .. 16) {
30 		stdout.flush(); // Flush contents of stdout to avoid half done outputs in CI Pipeline
31 		if (timeLimitSW.peek.total!"seconds" > argTimeLimit) {
32 			writeln("Time Limit execeeded, Abort test.");
33 			break;
34 		}
35 		foreach (ubyte i; 0 .. (256 / 32)) {
36 			int tsize = 2 ^^ 20 * size;
37 			auto test = new ubyte[tsize];
38 			test[] = cast(ubyte)(i * 32);
39 
40 			/* Test 1 */
41 			ubyte[16] hash1;
42 			{
43 				MD5 md5;
44 				sw.reset;
45 				sw.start;
46 				md5.start(); // Create a state
47 				for (int j = 0; j < tsize; j += tsize / 8) {
48 					md5.put(test[j .. j + tsize / 8]); // Hash the file in chunks
49 				}
50 				hash1 = md5.finish(); // Finalize the hash
51 				sw.stop;
52 			}
53 			auto time1 = sw.peek;
54 
55 			/* Test 2 */
56 			ubyte[16] hash3, hash4;
57 			{
58 				auto dmd5 = new MD5Digest();
59 				sw.reset;
60 				sw.start;
61 				hash3 = dmd5.digest(test[0 .. tsize]);
62 				sw.stop;
63 			}
64 			auto time2 = sw.peek;
65 			mbs_average += getMegaBytePerSeconds(tsize, time2);
66 			mbs_counts++;
67 
68 			/* Status output */
69 			version (unittest) {
70 			} else {
71 				import app : argVerbose;
72 
73 				if (argVerbose)
74 					writefln("Input: size=0x%08x fill=0x%02x, hash %s, %8fs, %8fs, %10.6f MB/s, %10.6f MB/s",
75 						tsize, i, hash1.toHexString,
76 						getFloatSecond(time1), getFloatSecond(time2),
77 						getMegaBytePerSeconds(tsize, time1), getMegaBytePerSeconds(tsize, time2));
78 			}
79 			/* Prepare CSV output */
80 			auto testCsv = MD5TestData(tsize, i, hash3, time1, time2);
81 			csvFile.addEntry(testCsv);
82 
83 			/* Check hash results */
84 			assert(hash1 == hash3, "Hashes mismatch");
85 		}
86 	}
87 	timeLimitSW.stop;
88 
89 	writefln("%35.35s: Average %12.6f MB/s", __FUNCTION__, mbs_average / mbs_counts);
90 	if (writeCSV)
91 		csvFile.writeFile;
92 	return rc;
93 }