public void References() { ResGen t = new ResGen(); ITaskItem[] throwawayInput = { new TaskItem("hello.resx") }; ITaskItem a = new TaskItem(); ITaskItem b = new TaskItem(); t.InputFiles = throwawayInput; t.ToolPath = Path.GetDirectoryName(ToolLocationHelper.GetPathToDotNetFrameworkSdkFile("resgen.exe", TargetDotNetFrameworkVersion.Latest)); a.ItemSpec = "foo.dll"; b.ItemSpec = "bar.dll"; ITaskItem[] singleReference = { a }; ITaskItem[] multipleReferences = { a, b }; Assert.Null(t.References); // "References should be null by default" CommandLine.ValidateNoParameterStartsWith(t, "/r:", true /* resgen 4.0 supports response files */); // Single reference t.References = singleReference; Assert.Equal(singleReference, t.References); // "New References value should be set" CommandLine.ValidateHasParameter(t, "/r:" + singleReference[0].ItemSpec, true /* resgen 4.0 supports response files */); // MultipleReferences t.References = multipleReferences; Assert.Equal(multipleReferences, t.References); // "New References value should be set" foreach (ITaskItem reference in multipleReferences) { CommandLine.ValidateHasParameter(t, "/r:" + reference.ItemSpec, true /* resgen 4.0 supports response files */); } // test cases where command line length is equal to the maximum allowed length and just above the maximum allowed length // we do some calculation here to do ensure that the resulting command lines match these cases (see Case 1 and 2 below) // reference switch adds space + "/r:", (4 characters) int referenceSwitchDelta = 4; //subtract one because leading space is added to command line arguments int maxCommandLineLength = 28000 - 1; int referencePathLength = 200; //min reference argument is " /r:a.dll" int minReferenceArgumentLength = referenceSwitchDelta + "a.dll".Length; // reference name is of the form aaa...aaa###.dll (repeated a characters followed by 3 // digit identifier for uniqueness followed by the .dll file extension StringBuilder referencePathBuilder = new StringBuilder(); referencePathBuilder.Append('a', referencePathLength - (3 /* 3 digit identifier */ + 4 /* file extension */)); string longReferenceNameBase = referencePathBuilder.ToString(); // reference switch length plus the length of the reference path int referenceArgumentLength = referencePathLength + referenceSwitchDelta; t = CreateCommandLineResGen(); // compute command line with only one reference switch so remaining added reference // arguments will have the same length, since the first reference argument added may not have a // leading space List <ITaskItem> references = new List <ITaskItem>(); references.Add(new TaskItem() { ItemSpec = "a.dll" }); t.References = references.ToArray(); int baseCommandLineLength = CommandLine.GetCommandLine(t, false).Length; Assert.True(baseCommandLineLength < maxCommandLineLength); // "Cannot create command line less than the maximum allowed command line" // calculate how many reference arguments will need to be added and what the length of the last argument // should be so that the command line length is equal to the maximum allowed length int remainder; int quotient = Math.DivRem(maxCommandLineLength - baseCommandLineLength, referenceArgumentLength, out remainder); if (remainder < minReferenceArgumentLength) { remainder += referenceArgumentLength; quotient--; } // compute the length of the last reference argument int lastReferencePathLength = remainder - (4 /* switch length */ + 4 /* file extension */); for (int i = 0; i < quotient; i++) { string refIndex = i.ToString().PadLeft(3, '0'); references.Add(new TaskItem() { ItemSpec = (longReferenceNameBase + refIndex + ".dll") }); } // // Case 1: Command line length is equal to the maximum allowed value // // create last reference argument referencePathBuilder.Clear(); referencePathBuilder.Append('b', lastReferencePathLength).Append(".dll"); ITaskItem lastReference = new TaskItem() { ItemSpec = referencePathBuilder.ToString() }; references.Add(lastReference); // set references t.References = references.ToArray(); int commandLineLength = CommandLine.GetCommandLine(t, false).Length; Assert.Equal(commandLineLength, maxCommandLineLength); ExecuteTaskAndVerifyLogDoesNotContainResource ( t, false, "ResGen.CommandTooLong", CommandLine.GetCommandLine(t, false).Length ); VerifyLogDoesNotContainResource((MockEngine)t.BuildEngine, GetPrivateLog(t), "ToolTask.CommandTooLong", typeof(ResGen).Name); // // Case 2: Command line length is one more than the maximum allowed value // // make last reference name longer by one character so that command line should become too long referencePathBuilder.Insert(0, 'b'); lastReference.ItemSpec = referencePathBuilder.ToString(); // reset ResGen task, since execution can change the command line t = CreateCommandLineResGen(); t.References = references.ToArray(); commandLineLength = CommandLine.GetCommandLine(t, false).Length; Assert.Equal(commandLineLength, maxCommandLineLength + 1); ExecuteTaskAndVerifyLogContainsErrorFromResource ( t, "ResGen.CommandTooLong", CommandLine.GetCommandLine(t, false).Length ); VerifyLogDoesNotContainResource((MockEngine)t.BuildEngine, GetPrivateLog(t), "ToolTask.CommandTooLong", typeof(ResGen).Name); }