Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / Microsoft.Build.Tasks / Test / Microsoft.Build.Tasks / CopyTest.cs
1 //
2 // CopyTest.cs
3 //  
4 // Author:
5 //   Ankit Jain (jankit@novell.com)
6 //
7 // Copyright 2009 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 using System;
29 using System.IO;
30 using Microsoft.Build.BuildEngine;
31 using NUnit.Framework;
32 using System.Text;
33
34 namespace MonoTests.Microsoft.Build.Tasks {
35
36         [TestFixture]
37         public class CopyTest {
38                 string source_path, target_path;
39
40                 [SetUp]
41                 public void CreateDir ()
42                 {
43                         source_path = Path.Combine (Path.Combine ("Test", "resources"), "Copy");
44                         Directory.CreateDirectory (source_path);
45                         target_path = Path.Combine (Path.Combine ("Test", "resources"), "Target");
46                         Directory.CreateDirectory (target_path);
47                 }
48
49                 [TearDown]
50                 public void RemoveDirectories ()
51                 {
52                         Directory.Delete (source_path, true);
53                         Directory.Delete (target_path, true);
54                 }
55
56                 [Test]
57                 public void TestCopy1 ()
58                 {
59                         Engine engine;
60                         Project project;
61                         string file_path = Path.Combine (source_path, "copy.txt");
62                         string target_file = Path.Combine (target_path, "copy.txt");
63
64                         using (File.CreateText (file_path)) { }
65
66                         string documentString = @"
67                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
68                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
69                                         <ItemGroup>
70                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
71                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
72                                         </ItemGroup>
73                                         <Target Name='1'>
74                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)' SkipUnchangedFiles='true' >
75                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
76                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
77                                                 </Copy>
78                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
79                                         </Target>
80                                 </Project>
81                         ";
82
83                         engine = new Engine (Consts.BinPath);
84                         project = engine.CreateNewProject ();
85
86                         TestMessageLogger testLogger = new TestMessageLogger ();
87                         engine.RegisterLogger (testLogger);
88
89                         project.LoadXml (documentString);
90
91                         if (!project.Build ("1")) {
92                                 var sb = new StringBuilder ();
93                                 testLogger.DumpMessages (sb);
94                                 Assert.Fail ("Build failed " + sb.ToString ());
95                         }
96                         Assert.IsTrue (File.Exists (target_file), "A2");
97
98                         BuildItemGroup big = project.GetEvaluatedItemsByName ("I0");
99                         Assert.AreEqual (1, big.Count, "A3");
100                         BuildItem bi = big [0];
101                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A4");
102                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A4");
103                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A5");
104
105                         big = project.GetEvaluatedItemsByName ("I1");
106                         Assert.AreEqual (1, big.Count, "A10");
107                         bi = big [0];
108                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A11");
109                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A12");
110                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A13");
111
112                         // build again, this time files won't get copied because
113                         // of SkipUnchangedFiles=true
114                         if (!project.Build ("1")) {
115                                 testLogger.DumpMessages ();
116                                 Assert.Fail ("Build failed #2");
117                         }
118                         Assert.IsTrue (File.Exists (target_file), "A20");
119
120                         big = project.GetEvaluatedItemsByName ("I0");
121                         Assert.AreEqual (1, big.Count, "A21");
122                         bi = big [0];
123                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A22");
124                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A23");
125                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A24");
126
127                         big = project.GetEvaluatedItemsByName ("I1");
128                         Assert.AreEqual (1, big.Count, "A25");
129                         bi = big [0];
130                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A26");
131                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A27");
132                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A28");
133                 }
134
135                 [Test]
136                 public void TestCopy2 ()
137                 {
138                         Engine engine;
139                         Project project;
140                         string [] file_paths = new string [] {
141                                 Path.Combine (source_path, "copy1.txt"),
142                                 Path.Combine (source_path, "copy2.txt")
143                         };
144
145                         using (File.CreateText (file_paths[0])) { }
146                         using (File.CreateText (file_paths[1])) { }
147
148                         string documentString = @"
149                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
150                                         <PropertyGroup><TargetPath>" + target_path + @"</TargetPath></PropertyGroup>
151                                         <ItemGroup>
152                                                 <SFiles Include='" + file_paths [0] + @"'><Md>1</Md></SFiles>
153                                                 <SFiles Include='" + file_paths [1] + @"'><Md>2</Md></SFiles>
154                                         </ItemGroup>
155                                         <Target Name='1'>
156                                                 <Copy SourceFiles='@(SFiles)' DestinationFolder='$(TargetPath)' SkipUnchangedFiles='true' >
157                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
158                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
159                                                 </Copy>
160                                         </Target>
161                                 </Project>
162                         ";
163                         engine = new Engine (Consts.BinPath);
164                         project = engine.CreateNewProject ();
165
166                         TestMessageLogger testLogger = new TestMessageLogger ();
167                         engine.RegisterLogger (testLogger);
168
169                         project.LoadXml (documentString);
170
171                         if (!project.Build ("1")) {
172                                 testLogger.DumpMessages ();
173                                 Assert.Fail ("Build failed");
174                         }
175
176                         CheckCopyBuildItems (project, file_paths, target_path, "A1");
177
178                         // build again, this time files won't get copied because
179                         // of SkipUnchangedFiles=true
180                         if (!project.Build ("1")) {
181                                 testLogger.DumpMessages ();
182                                 Assert.Fail ("Build failed #2");
183                         }
184                         CheckCopyBuildItems (project, file_paths, target_path, "A2");
185                 }
186
187                 [Test]
188                 public void TestCopy_EmptySources () {
189                         Engine engine;
190                         Project project;
191
192                         string documentString = @"
193                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
194                                         <Target Name='1'>
195                                                 <Copy SourceFiles='@(NonExistantSourceFiles)' DestinationFolder='$(TargetPath)' SkipUnchangedFiles='true' >
196                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
197                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
198                                                 </Copy>
199                                         </Target>
200                                 </Project>
201                         ";
202                         engine = new Engine (Consts.BinPath);
203                         project = engine.CreateNewProject ();
204
205                         TestMessageLogger testLogger = new TestMessageLogger ();
206                         engine.RegisterLogger (testLogger);
207
208                         project.LoadXml (documentString);
209
210                         
211                         if (!project.Build ("1")) {
212                                 testLogger.DumpMessages ();
213                                 Assert.Fail ("Build failed");
214                         }
215                 }
216
217                 [Test]
218                 public void TestCopy_EmptyDestFolder () {
219                         Engine engine;
220                         Project project;
221
222                         string documentString = @"
223                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
224                                         <ItemGroup>
225                                                 <SFiles Include='foo.txt'><Md>1</Md></SFiles>
226                                         </ItemGroup>
227                                         <Target Name='1'>
228                                                 <Copy SourceFiles='@(SFiles)' DestinationFolder='@(NonExistant)' DestinationFiles='@(NonExistant)' SkipUnchangedFiles='true' >
229                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
230                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
231                                                 </Copy>
232                                         </Target>
233                                 </Project>
234                         ";
235                         engine = new Engine (Consts.BinPath);
236                         project = engine.CreateNewProject ();
237
238                         TestMessageLogger testLogger = new TestMessageLogger ();
239                         engine.RegisterLogger (testLogger);
240
241                         project.LoadXml (documentString);
242                         if (project.Build ("1")) {
243                                 testLogger.DumpMessages ();
244                                 Assert.Fail ("Build should have failed");
245                         }
246                 }
247
248                 [Test]
249                 public void TestCopy_ReadOnlyUpdate ()
250                 {
251                         Engine engine;
252                         Project project;
253                         string file_path = Path.Combine (source_path, "copyro.txt");
254                         string target_file = Path.Combine (target_path, "copyro.txt");                  
255
256                         using (File.CreateText (file_path)) { }
257                         
258                         string documentString = @"
259                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
260                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
261                                         <ItemGroup>
262                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
263                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
264                                         </ItemGroup>
265                                         <Target Name='1'>
266                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)' >
267                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
268                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
269                                                 </Copy>
270                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
271                                         </Target>
272                                 </Project>
273                         ";
274
275                         engine = new Engine (Consts.BinPath);
276                         project = engine.CreateNewProject ();
277
278                         TestMessageLogger testLogger = new TestMessageLogger ();
279                         engine.RegisterLogger (testLogger);
280
281                         project.LoadXml (documentString);
282
283                         if (!project.Build ("1")) {
284                                 testLogger.DumpMessages ();
285                                 Assert.Fail ("Build failed");
286                         }
287                         Assert.IsTrue (File.Exists (target_file), "A2");
288                         Assert.AreEqual (FileAttributes.Normal, File.GetAttributes (target_file), "A3");                                        
289                 }
290
291 #if NET_3_5
292                 [Test]
293                 public void TestCopy_OverwriteReadOnlyTrue ()
294                 {
295                         Engine engine;
296                         Project project;
297                         string file_path = Path.Combine (source_path, "copyro1.txt");
298                         string target_file = Path.Combine (target_path, "copyro1.txt");                 
299
300                         using (File.CreateText (file_path)) { }
301                         using (File.CreateText (target_file)) { }
302
303                         File.SetAttributes (target_file, FileAttributes.ReadOnly);
304                         Assert.AreEqual (FileAttributes.ReadOnly, File.GetAttributes (target_file), "A1");
305                         
306                         string documentString = @"
307                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""3.5"">
308                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
309                                         <ItemGroup>
310                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
311                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
312                                         </ItemGroup>
313                                         <Target Name='1'>
314                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)' OverwriteReadOnlyFiles='true'>
315                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
316                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
317                                                 </Copy>
318                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
319                                         </Target>
320                                 </Project>
321                         ";
322
323                         engine = new Engine (Consts.BinPath);
324                         project = engine.CreateNewProject ();
325
326                         TestMessageLogger testLogger = new TestMessageLogger ();
327                         engine.RegisterLogger (testLogger);
328
329                         project.LoadXml (documentString);
330
331                         if (!project.Build ("1")) {
332                                 var sb = new StringBuilder ();
333                                 testLogger.DumpMessages (sb);
334                                 Assert.Fail ("Build failed " + sb.ToString ());
335                         }
336                         Assert.IsTrue (File.Exists (target_file), "A2");
337                         Assert.AreEqual (FileAttributes.Normal, File.GetAttributes (target_file), "A3");                                        
338                 }
339
340                 [Test]
341                 public void TestCopy_OverwriteReadOnlyFalse ()
342                 {
343                         Engine engine;
344                         Project project;
345                         string file_path = Path.Combine (source_path, "copyro2.txt");
346                         string target_file = Path.Combine (target_path, "copyro2.txt");                 
347
348                         using (File.CreateText (file_path)) { }
349                         using (File.CreateText (target_file)) { }
350
351                         File.SetAttributes (target_file, FileAttributes.ReadOnly);
352                         Assert.AreEqual (FileAttributes.ReadOnly, File.GetAttributes (target_file), "A1");
353                         
354                         string documentString = @"
355                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
356                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
357                                         <ItemGroup>
358                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
359                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
360                                         </ItemGroup>
361                                         <Target Name='1'>
362                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)'>
363                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
364                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
365                                                 </Copy>
366                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
367                                         </Target>
368                                 </Project>
369                         ";
370
371                         engine = new Engine (Consts.BinPath);
372                         project = engine.CreateNewProject ();
373
374                         TestMessageLogger testLogger = new TestMessageLogger ();
375                         engine.RegisterLogger (testLogger);
376
377                         project.LoadXml (documentString);
378
379                         // build should fail because of the readonly target file
380                         Assert.IsFalse (project.Build ("1"));
381                         
382                         File.SetAttributes (target_file, FileAttributes.Normal);
383                 }
384 #endif
385
386                 void CheckCopyBuildItems (Project project, string [] source_files, string destination_folder, string prefix)
387                 {
388                         int num = source_files.Length;
389                         for (int i = 0; i < num; i ++)
390                                 Assert.IsTrue (File.Exists (source_files [i]), prefix + " C1");
391
392                         BuildItemGroup big = project.GetEvaluatedItemsByName ("I0");
393
394                         Assert.AreEqual (num, big.Count, prefix + " C2");
395                         for (int i = 0; i < num; i++) {
396                                 string suffix = (i + 1).ToString ();
397                                 BuildItem bi = big [i];
398                                 Assert.AreEqual (Path.Combine (destination_folder, Path.GetFileName (source_files [i])),
399                                         bi.FinalItemSpec, prefix + " C3 #" + suffix);
400
401                                 Assert.AreEqual (suffix, bi.GetMetadata ("Md"), prefix + " C4 #" + suffix);
402                         }
403
404                         big = project.GetEvaluatedItemsByName ("I1");
405                         Assert.AreEqual (num, big.Count, prefix + " C6");
406                         for (int i = 0; i < num; i++) {
407                                 string suffix = (i + 1).ToString ();
408                                 BuildItem bi = big [i];
409                                 Assert.AreEqual (Path.Combine (destination_folder, Path.GetFileName (source_files [i])),
410                                         bi.FinalItemSpec, prefix + " C7 #" + suffix);
411                                 Assert.AreEqual (suffix, bi.GetMetadata ("Md"), prefix + " C8 #" + suffix);
412                         }
413                  }
414         }
415 }