1 module ut.wrap.traits; 2 3 import test; 4 import xlld.wrap.traits; 5 import xlld.wrap.worksheet; 6 7 8 /// return a WorksheetFunction for a double function(double) with no 9 /// optional arguments 10 WorksheetFunction makeWorksheetFunction(wstring name, wstring typeText) @safe pure nothrow { 11 return 12 WorksheetFunction( 13 Procedure(name), 14 TypeText(typeText), 15 FunctionText(name), 16 Optional( 17 ArgumentText(""w), 18 MacroType("1"w), 19 Category(""w), 20 ShortcutText(""w), 21 HelpTopic(""w), 22 FunctionHelp(""w), 23 ArgumentHelp([""w]), 24 ) 25 ); 26 } 27 28 /// 29 WorksheetFunction doubleToDoubleFunction(wstring name) @safe pure nothrow { 30 auto ret = makeWorksheetFunction(name, "BB"w); 31 ret.optional.argumentText = ArgumentText("n"); // See test.xl_funcs.FuncMulByTwo 32 return ret; 33 } 34 35 /// 36 WorksheetFunction FP12ToDoubleFunction(wstring name) @safe pure nothrow { 37 auto ret = makeWorksheetFunction(name, "BK%"w); 38 ret.optional.argumentText = ArgumentText("cells"); // See test.xl_funcs.FuncFP12 39 return ret; 40 } 41 42 /// 43 WorksheetFunction operToOperFunction(wstring name) @safe pure nothrow { 44 auto ret = makeWorksheetFunction(name, "UU"w); 45 ret.optional.argumentText = ArgumentText("n"); // See test.xl_funcs.FuncFib 46 return ret; 47 } 48 49 WorksheetFunction asyncFunction(wstring name) @safe pure nothrow { 50 auto ret = makeWorksheetFunction(name, ">UX"w); 51 ret.optional.argumentHelp.add(""); // FuncAsync has two parameters 52 ret.optional.argumentText = ArgumentText("n;asyncHandle"); 53 return ret; 54 } 55 56 /// 57 @("getWorksheetFunction for double -> double functions with no extra attributes") 58 @safe pure unittest { 59 extern(Windows) double foo(double n) nothrow @nogc { return 0; } 60 getWorksheetFunction!foo.shouldEqual(doubleToDoubleFunction("foo")); 61 62 extern(Windows) double bar(double n) nothrow @nogc { return 0; } 63 getWorksheetFunction!bar.shouldEqual(doubleToDoubleFunction("bar")); 64 } 65 66 /// 67 @("getWorksheetFunction for double -> int functions should fail") 68 @safe pure unittest { 69 extern(Windows) double foo(int) { return 0; } 70 getWorksheetFunction!foo.shouldThrowWithMessage("Unsupported function type double(int) for foo"); 71 } 72 73 /// 74 @("getworksheetFunction with @Register in order") 75 @safe pure unittest { 76 77 @Register(ArgumentText("my arg txt"), MacroType("macro")) 78 extern(Windows) double foo(double) nothrow; 79 80 auto expected = doubleToDoubleFunction("foo"); 81 expected.argumentText = ArgumentText("my arg txt"); 82 expected.macroType = MacroType("macro"); 83 84 getWorksheetFunction!foo.shouldEqual(expected); 85 } 86 87 /// 88 @("getworksheetFunction with @Register out of order") 89 @safe pure unittest { 90 91 @Register(HelpTopic("I need somebody"), ArgumentText("my arg txt")) 92 extern(Windows) double foo(double) nothrow; 93 94 auto expected = doubleToDoubleFunction("foo"); 95 expected.argumentText = ArgumentText("my arg txt"); 96 expected.helpTopic = HelpTopic("I need somebody"); 97 98 getWorksheetFunction!foo.shouldEqual(expected); 99 } 100 101 102 @("getWorksheetFunction with @ExcelParameter") 103 @safe pure unittest { 104 extern(Windows) double withParamUDA(@ExcelParameter("the double") double d) nothrow; 105 106 auto expected = doubleToDoubleFunction("withParamUDA"); 107 expected.optional.argumentHelp = ArgumentHelp("the double"); 108 expected.optional.argumentText = ArgumentText("d"); 109 110 getWorksheetFunction!withParamUDA.should == expected; 111 } 112 113 114 @safe pure unittest { 115 extern(Windows) double doubleToDouble(double) nothrow; 116 static assert(isWorksheetFunction!doubleToDouble); 117 118 extern(Windows) LPXLOPER12 operToOper(LPXLOPER12) nothrow; 119 static assert(isWorksheetFunction!operToOper); 120 121 extern(Windows) void funcAsync(LPXLOPER12 n, LPXLOPER12 asyncHandle) nothrow; 122 static assert(isWorksheetFunction!funcAsync); 123 124 LPXLOPER12 operToOperWrongLinkage(LPXLOPER12) nothrow; 125 static assert(isWorksheetFunctionModuloLinkage!operToOperWrongLinkage); 126 static assert(!isWorksheetFunction!operToOperWrongLinkage); 127 128 enum MyEnum { foo, bar, baz, } 129 130 extern(Windows) MyEnum FuncEnumRet(LPXLOPER12 n) nothrow; 131 static assert(!isWorksheetFunction!FuncEnumRet); 132 133 extern(Windows) LPXLOPER12 FuncEnumArg(MyEnum _) nothrow; 134 static assert(!isWorksheetFunction!FuncEnumArg); 135 } 136 137 138 @("getWorksheetFunctions on test.xl_funcs") 139 @safe pure unittest { 140 getModuleWorksheetFunctions!"test.xl_funcs".shouldEqual( 141 [ 142 doubleToDoubleFunction("FuncMulByTwo"), 143 FP12ToDoubleFunction("FuncFP12"), 144 operToOperFunction("FuncFib"), 145 asyncFunction("FuncAsync"), 146 ] 147 ); 148 } 149 150 @("template mixin for getWorkSheetFunctions for test.xl_funcs") 151 unittest { 152 import xlld.wrap.worksheet; 153 154 // mixin the function here then call it to see if it does what it's supposed to 155 mixin(implGetWorksheetFunctionsString!"test.xl_funcs"); 156 getWorksheetFunctions.shouldEqual( 157 [ 158 doubleToDoubleFunction("FuncMulByTwo"), 159 FP12ToDoubleFunction("FuncFP12"), 160 operToOperFunction("FuncFib"), 161 asyncFunction("FuncAsync"), 162 ] 163 ); 164 } 165 166 @("implGetWorksheetFunctionsString runtime") 167 unittest { 168 import xlld.wrap.worksheet; 169 170 // mixin the function here then call it to see if it does what it's supposed to 171 mixin(implGetWorksheetFunctionsString("test.xl_funcs")); 172 getWorksheetFunctions.shouldEqual( 173 [ 174 doubleToDoubleFunction("FuncMulByTwo"), 175 FP12ToDoubleFunction("FuncFP12"), 176 operToOperFunction("FuncFib"), 177 asyncFunction("FuncAsync"), 178 ] 179 ); 180 } 181 182 183 @("worksheet functions to .def file") 184 unittest { 185 dllDefFile!"test.xl_funcs"("myxll32.dll", "Simple D add-in").shouldEqual( 186 DllDefFile( 187 [ 188 Statement("LIBRARY", "myxll32.dll"), 189 Statement("EXPORTS", 190 [ 191 "xlAutoOpen", 192 "xlAutoClose", 193 "xlAutoFree12", 194 "FuncMulByTwo", 195 "FuncFP12", 196 "FuncFib", 197 "FuncAsync", 198 ]), 199 ] 200 ) 201 ); 202 } 203 204 205 @("getTypeText") 206 @safe pure unittest { 207 import std.conv: to; // working around unit-threaded bug 208 209 double foo(double); 210 getTypeText!foo.to!string.shouldEqual("BB"); 211 212 double bar(FP12*); 213 getTypeText!bar.to!string.shouldEqual("BK%"); 214 215 FP12* baz(FP12*); 216 getTypeText!baz.to!string.shouldEqual("K%K%"); 217 218 FP12* qux(double); 219 getTypeText!qux.to!string.shouldEqual("K%B"); 220 221 LPXLOPER12 fun(LPXLOPER12); 222 getTypeText!fun.to!string.shouldEqual("UU"); 223 224 void void_(LPXLOPER12, LPXLOPER12); 225 getTypeText!void_.to!string.shouldEqual(">UU"); 226 227 @Async 228 void async(LPXLOPER12, LPXLOPER12); 229 getTypeText!async.to!string.shouldEqual(">UX"); 230 }