1 /***************************************************************
2  * Features for unit testing
3  * 
4  * Fine-tune the output destination of coverage, etc.
5  */
6 module examples.ut;
7 
8 debug shared static this()
9 {
10 	import core.stdc.stdio;
11 	setvbuf(stdout, null, _IONBF, 0);
12 }
13 ///
14 version (D_Coverage)
15 {
16 	private extern (C) void dmd_coverDestPath( string pathname );
17 	private extern (C) void dmd_coverSourcePath( string pathname );
18 	private extern (C) void dmd_coverSetMerge( bool flag );
19 	
20 	private struct CovOpt
21 	{
22 		string dir;
23 		bool   merge;
24 	}
25 	
26 	private CovOpt getCovOptFromString(string str)
27 	{
28 		import std.string, std.getopt, std.algorithm, std.array;
29 		CovOpt ret;
30 		auto args = [""] ~ str.splitLines.map!(a => a.strip).filter!(a => a.length > 0).array;
31 		args.getopt(
32 			config.caseSensitive,
33 			config.bundling,
34 			config.passThrough,
35 			"d|dir|coverage_dir", &ret.dir,
36 			"m|merge|coverage_merge", &ret.merge);
37 		return ret;
38 	}
39 	
40 	@system unittest
41 	{
42 		auto opt = getCovOptFromString(`
43 			-d=xxx
44 			`);
45 		assert(opt.dir == "xxx");
46 		assert(!opt.merge);
47 		opt = getCovOptFromString(`
48 			--dir=cov
49 			--xxx
50 			-m
51 			`);
52 		assert(opt.dir == "cov");
53 		assert(opt.merge);
54 		opt = getCovOptFromString(null);
55 		assert(opt.dir.length == 0);
56 		assert(!opt.merge);
57 		
58 		opt = getCovOptFromString(`-md=xxx`);
59 		assert(opt.dir == "xxx");
60 		assert(opt.merge);
61 		
62 	}
63 	
64 	private CovOpt getCovOpt(string[] searchDirs = ["."], string[] searchFileNames = [".coverageopt"])
65 	{
66 		import std.file, std.path;
67 		CovOpt ret;
68 		foreach (d; searchDirs)
69 		{
70 			foreach (f; searchFileNames)
71 			{
72 				auto filepath = d.buildPath(f);
73 				if (filepath.exists && filepath.isFile)
74 				{
75 					ret = getCovOptFromString(readText(filepath));
76 					break;
77 				}
78 			}
79 			if (ret.dir.length == 0 && d.exists && d.isDir)
80 			{
81 				ret.dir = d;
82 				break;
83 			}
84 		}
85 		return ret;
86 	}
87 	
88 	@system unittest
89 	{
90 		import std.file, std.path;
91 		auto opt = getCovOpt(["."], ["nul"]);
92 		assert(opt.dir == ".");
93 		assert(!opt.merge);
94 		
95 		auto dir = "._._._workdir_._._";
96 		auto file = ".dat";
97 		dir.mkdir();
98 		scope (exit)
99 			dir.rmdirRecurse();
100 		dir.buildPath(file).write("-d=dir");
101 		opt = getCovOpt([dir], [file]);
102 		assert(opt.dir == "dir");
103 		assert(!opt.merge);
104 	}
105 	
106 	private CovOpt getCovOpt(string[string] env)
107 	{
108 		import std.algorithm, std.string;
109 		CovOpt ret;
110 		if (auto p = "COVERAGE_DIR" in env)
111 			ret.dir = strip(*p);
112 		if (auto p = "COVERAGE_MERGE" in env)
113 			ret.merge = ["merge", "true", "yes"].any!(a => a == *p );
114 		return ret;
115 	}
116 	
117 	@system unittest
118 	{
119 		auto opt = getCovOpt(["COVERAGE_DIR": "xxx", "COVERAGE_MERGE": "yes"]);
120 		assert(opt.dir == "xxx" && opt.merge);
121 		
122 		opt = getCovOpt(["COVERAGE_DIR": "aaa", "COVERAGE_MERGE": "true"]);
123 		assert(opt.dir == "aaa" && opt.merge);
124 		
125 		opt = getCovOpt(["COVERAGE_MERGE": "merge"]);
126 		assert(opt.dir.length == 0 && opt.merge);
127 		
128 		opt = getCovOpt(["COVERAGE_DIR": "xxx", "COVERAGE_MERGE": "aaa"]);
129 		assert(opt.dir == "xxx" && !opt.merge);
130 		
131 		opt = getCovOpt(["COVERAGE_DIR": "xxx"]);
132 		assert(opt.dir == "xxx" && !opt.merge);
133 	}
134 	
135 	private CovOpt getCovOpt(string[string] env, string[] searchDirs, string[] searchFileNames)
136 	{
137 		auto opt = getCovOpt(env);
138 		if (opt.dir.length > 0)
139 			return opt;
140 		return getCovOpt(searchDirs, searchFileNames);
141 	}
142 	
143 	@system unittest
144 	{
145 		auto opt = getCovOpt(["xx": "yy"], ["."], [".xxx"]);
146 		assert(opt.dir == ".");
147 		opt = getCovOpt(["COVERAGE_DIR": "yy"], ["."], [".xxx"]);
148 		assert(opt.dir == "yy");
149 	}
150 	
151 	
152 	private CovOpt getCovOpt()
153 	{
154 		import std.process, std.path, std.file;
155 		return getCovOpt(environment.toAA, [".",
156 			thisExePath.dirName.buildPath("cov"),
157 			thisExePath.dirName.buildPath(".cov"),
158 			"cov", ".cov", "."], [".coverageopt"]);
159 	}
160 	
161 	shared static this()
162 	{
163 		import std.file, std.path;
164 		auto covopt = getCovOpt();
165 		if (covopt.dir.length > 0)
166 		{
167 			enum rootDir = __FILE_FULL_PATH__.dirName.dirName.buildNormalizedPath();
168 			if (!covopt.dir.exists) mkdirRecurse(covopt.dir);
169 			dmd_coverSetMerge(covopt.merge);
170 			dmd_coverSourcePath(rootDir);
171 			dmd_coverDestPath(covopt.dir);
172 		}
173 	}
174 }