Skip to content

Commit 923fd26

Browse files
committed
CCNET-1786: VSTS Source Control is broken
CCNET-1774: Receive an unauthorized access exception when connecting to TFS CCNET-1710: The new Team Foundation Server (vsts) source control solution in 1.5.0 CTP does not supply the login credentials for all calls resulting in 'not authorized' errors Patched to ensure domains are present in all requests to TFS servers: * Refactored slightly to prevent a duplicate call to TFS' "workspaces" command. * Removed redundant try/catch blocks. * Added support for sourcing TF.exe from Visual Studio 2010 * Renamed inconsistant member variables to UpperCamalCase for consistency with the rest of the code. * Added unit tests to verify the correct authentication details are provided during GetHistory and GetSource operations. Not fixed: * Time zone errors - could not accurately reproduce. Could do with some more specific examples or test cases Patch by David Whitney
1 parent 3fc32e4 commit 923fd26

3 files changed

Lines changed: 404 additions & 225 deletions

File tree

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
using System;
2+
using System.Globalization;
3+
using System.IO;
4+
using NMock;
5+
using NUnit.Framework;
6+
using ThoughtWorks.CruiseControl.Core;
7+
using ThoughtWorks.CruiseControl.Core.Sourcecontrol;
8+
using ThoughtWorks.CruiseControl.Core.Util;
9+
using ThoughtWorks.CruiseControl.Remote;
10+
11+
namespace ThoughtWorks.CruiseControl.UnitTests.Core.Sourcecontrol
12+
{
13+
[TestFixture]
14+
public class VstsTest: ProcessExecutorTestFixtureBase
15+
{
16+
private IRegistry mockRegistry;
17+
private VstsHistoryParser historyParser;
18+
private Vsts vsts;
19+
private DateTime today;
20+
private DateTime yesterday;
21+
22+
private const string fakeTfsPath = "http://faketfs:8080";
23+
private const string fakeProjectPath = "$/TeamProjectName/path";
24+
private const string fakeUsername = "username";
25+
private const string fakePassword = "password";
26+
27+
private class RegistryStub: IRegistry
28+
{
29+
public const string DEFAULT_VS2010_EXE_PATH = @"Software\Wow6432Node\Microsoft\VisualStudio\10.0";
30+
31+
public string GetLocalMachineSubKeyValue(string path, string name)
32+
{
33+
if(path == DEFAULT_VS2010_EXE_PATH && name == "InstallDir")
34+
{
35+
return "mockPath";
36+
}
37+
throw new NotImplementedException();
38+
}
39+
40+
public string GetExpectedLocalMachineSubKeyValue(string path, string name)
41+
{
42+
throw new NotImplementedException();
43+
}
44+
}
45+
46+
[SetUp]
47+
public void SetUp()
48+
{
49+
50+
CreateProcessExecutorMock("mockPath\\TF.exe");
51+
mockRegistry = new RegistryStub();
52+
historyParser = new VstsHistoryParser();
53+
54+
vsts = new Vsts((ProcessExecutor)mockProcessExecutor.MockInstance, historyParser, mockRegistry);
55+
vsts.Username = fakeUsername;
56+
vsts.Password = fakePassword;
57+
vsts.WorkingDirectory = DefaultWorkingDirectory;
58+
vsts.Server = fakeTfsPath;
59+
vsts.ProjectPath = fakeProjectPath;
60+
61+
today = DateTime.Now;
62+
yesterday = today.AddDays(-1);
63+
}
64+
65+
[TearDown]
66+
public void TearDown()
67+
{
68+
Verify();
69+
}
70+
71+
[Test]
72+
public void VerifyGetModificationsProcessInfoArguments()
73+
{
74+
IntegrationResult from = IntegrationResultMother.CreateSuccessful(yesterday);
75+
IntegrationResult to = IntegrationResultMother.CreateSuccessful(today);
76+
77+
ExpectToExecuteArguments(string.Format("dir /folders /server:{0} \"{1}\" /login:{2},{3}",
78+
fakeTfsPath,
79+
fakeProjectPath,
80+
fakeUsername,
81+
fakePassword));
82+
83+
ExpectToExecuteArguments(string.Format("history -noprompt -server:{0} \"{1}\" -version:D{2}~D{3} -recursive -format:detailed /login:{4},{5}",
84+
fakeTfsPath,
85+
fakeProjectPath,
86+
FormatCommandDate(from.StartTime),
87+
FormatCommandDate(to.StartTime),
88+
fakeUsername,
89+
fakePassword));
90+
91+
vsts.GetModifications(from, to);
92+
}
93+
94+
[Test]
95+
public void VerifyGetModificationsProcessInfoArgumentsWhenDomainIsSpecified()
96+
{
97+
IntegrationResult from = IntegrationResultMother.CreateSuccessful(yesterday);
98+
IntegrationResult to = IntegrationResultMother.CreateSuccessful(today);
99+
100+
vsts.Domain = "testDomain";
101+
string expectedUsername = vsts.Domain + "\\" + fakeUsername;
102+
103+
ExpectToExecuteArguments(string.Format("dir /folders /server:{0} \"{1}\" /login:{2},{3}",
104+
fakeTfsPath,
105+
fakeProjectPath,
106+
expectedUsername,
107+
fakePassword));
108+
109+
ExpectToExecuteArguments(string.Format("history -noprompt -server:{0} \"{1}\" -version:D{2}~D{3} -recursive -format:detailed /login:{4},{5}",
110+
fakeTfsPath,
111+
fakeProjectPath,
112+
FormatCommandDate(from.StartTime),
113+
FormatCommandDate(to.StartTime),
114+
expectedUsername,
115+
fakePassword));
116+
117+
vsts.GetModifications(from, to);
118+
}
119+
120+
[Test]
121+
public void VerifyGetSourceProcessInfoArguments()
122+
{
123+
IntegrationResult result = new IntegrationResult("testProject", "testWorkingDir", "testArtifactDir",
124+
new IntegrationRequest(BuildCondition.ForceBuild,"testSource", "testUsername"),
125+
new IntegrationSummary(IntegrationStatus.Unknown,"testLabel", "testLastSuccessfulLabel", DateTime.Now));
126+
vsts.AutoGetSource = true;
127+
vsts.Domain = "testDomain";
128+
string expectedUsername = vsts.Domain + "\\" + fakeUsername;
129+
130+
ExpectToExecuteArguments(string.Format("dir /folders /server:{0} \"{1}\" /login:{2},{3}",
131+
fakeTfsPath,
132+
fakeProjectPath,
133+
expectedUsername,
134+
fakePassword));
135+
136+
ExpectToExecuteArguments(string.Format("workspaces /computer:{1} -server:{0} /format:detailed \"CCNET\" /login:{2},{3}",
137+
fakeTfsPath,
138+
Environment.MachineName,
139+
expectedUsername,
140+
fakePassword));
141+
142+
ExpectToExecuteArguments(string.Format(@"workfold /map ""{0}"" ""{1}"" /server:{2} /workspace:CCNET /login:{3},{4}",
143+
fakeProjectPath,
144+
DefaultWorkingDirectory,
145+
fakeTfsPath,
146+
expectedUsername,
147+
fakePassword));
148+
149+
string getCommand = string.Format("get /force /recursive /noprompt \"{0}\" /login:{1},{2}",
150+
DefaultWorkingDirectory,
151+
expectedUsername,
152+
fakePassword);
153+
154+
ProcessInfo info = NewProcessInfo(getCommand, DefaultWorkingDirectory);
155+
info.TimeOut = 3600000;
156+
ExpectToExecute(info);
157+
158+
159+
vsts.GetSource(result);
160+
}
161+
162+
[Test]
163+
public void VerifyGetSourceProcessInfoArgumentsWhenDomainIsSpecified()
164+
{
165+
IntegrationResult result = new IntegrationResult("testProject", "testWorkingDir", "testArtifactDir",
166+
new IntegrationRequest(BuildCondition.ForceBuild,"testSource", "testUsername"),
167+
new IntegrationSummary(IntegrationStatus.Unknown,"testLabel", "testLastSuccessfulLabel", DateTime.Now));
168+
vsts.AutoGetSource = true;
169+
170+
ExpectToExecuteArguments(string.Format("dir /folders /server:{0} \"{1}\" /login:{2},{3}",
171+
fakeTfsPath,
172+
fakeProjectPath,
173+
fakeUsername,
174+
fakePassword));
175+
176+
ExpectToExecuteArguments(string.Format("workspaces /computer:{1} -server:{0} /format:detailed \"CCNET\" /login:{2},{3}",
177+
fakeTfsPath,
178+
Environment.MachineName,
179+
fakeUsername,
180+
fakePassword));
181+
182+
ExpectToExecuteArguments(string.Format(@"workfold /map ""{0}"" ""{1}"" /server:{2} /workspace:CCNET /login:{3},{4}",
183+
fakeProjectPath,
184+
DefaultWorkingDirectory,
185+
fakeTfsPath,
186+
fakeUsername,
187+
fakePassword));
188+
189+
string getCommand = string.Format("get /force /recursive /noprompt \"{0}\" /login:{1},{2}",
190+
DefaultWorkingDirectory,
191+
fakeUsername,
192+
fakePassword);
193+
194+
ProcessInfo info = NewProcessInfo(getCommand, DefaultWorkingDirectory);
195+
info.TimeOut = 3600000;
196+
ExpectToExecute(info);
197+
198+
199+
vsts.GetSource(result);
200+
}
201+
202+
private static string FormatCommandDate(DateTime date)
203+
{
204+
return date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture);
205+
}
206+
207+
}
208+
}

project/UnitTests/UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@
357357
<Compile Include="Core\Publishers\PackageFileTests.cs" />
358358
<Compile Include="Core\Publishers\PackagePublisherTests.cs" />
359359
<Compile Include="Core\Label\AssemblyVersionLabellerTest.cs" />
360+
<Compile Include="Core\SourceControl\VstsTest.cs" />
360361
<Compile Include="Core\Tasks\CruiseServerControlTaskTests.cs" />
361362
<Compile Include="Core\Triggers\RollUpTriggerTest.cs" />
362363
<Compile Include="Core\Util\InstanceAssert.cs" />

0 commit comments

Comments
 (0)