1 module check; 2 3 import model; 4 import std.typecons; 5 version (unittest) import unit_threaded; 6 7 struct Checker 8 { 9 private Dependency[] explicitDependencies; 10 11 private Dependency[] implicitDependencies; 12 13 this(Dependency[] targetDependencies, bool simplify) 14 { 15 import std.algorithm : partition; 16 17 bool implict(Dependency dependency) 18 { 19 import std.algorithm : any, filter; 20 21 return targetDependencies 22 .filter!(targetDependency => targetDependency != dependency) 23 .any!(targetDependency => targetDependency.implies(dependency)); 24 } 25 26 auto dependencies = targetDependencies.dup; 27 28 if (simplify) 29 { 30 this.explicitDependencies = dependencies.partition!implict; 31 this.implicitDependencies = dependencies[0 .. $ - this.explicitDependencies.length]; 32 return; 33 } 34 this.implicitDependencies = dependencies; 35 } 36 37 bool allows(Dependency actualDependency) 38 { 39 import std.algorithm : any; 40 41 return this.explicitDependencies.any!(dependency => actualDependency.implies(dependency)) 42 || this.implicitDependencies.any!(dependency => actualDependency == dependency); 43 } 44 } 45 46 @("check for allowed dependencies") 47 unittest 48 { 49 auto dependencies = [ 50 Dependency("a", "b"), 51 Dependency("a.x", "b.y"), 52 Dependency("b", "c"), 53 ]; 54 55 with (Checker(dependencies, Yes.simplify)) 56 { 57 allows(Dependency("a", "b")).shouldBeTrue; 58 allows(Dependency("a.x", "b.y")).shouldBeTrue; 59 allows(Dependency("b", "c")).shouldBeTrue; 60 allows(Dependency("b.x", "c")).shouldBeTrue; // implies explicit dependency 61 62 allows(Dependency("a.x", "b")).shouldBeFalse; // implies implicit dependency 63 } 64 } 65 66 bool implies(Dependency lhs, Dependency rhs) 67 { 68 import std.algorithm : startsWith; 69 70 return lhs.client.names.startsWith(rhs.client.names) 71 && lhs.supplier.names.startsWith(rhs.supplier.names); 72 } 73 74 @("check for implied dependencies") 75 unittest 76 { 77 Dependency("a", "b").implies(Dependency("a", "b")).shouldBeTrue; 78 Dependency("a.x", "b.y").implies(Dependency("a", "b")).shouldBeTrue; 79 80 Dependency("a.x", "b").implies(Dependency("a", "b.y")).shouldBeFalse; 81 Dependency("aa", "bb").implies(Dependency("a", "b")).shouldBeFalse; 82 }