Merge pull request #228 from QuickJack/3e163743eda89cc8c239779a75dd245be12aee3c
[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
33 namespace MonoTests.Microsoft.Build.Tasks {
34
35         [TestFixture]
36         public class CopyTest {
37                 string source_path, target_path;
38
39                 [SetUp]
40                 public void CreateDir ()
41                 {
42                         source_path = Path.Combine (Path.Combine ("Test", "resources"), "Copy");
43                         Directory.CreateDirectory (source_path);
44                         target_path = Path.Combine (Path.Combine ("Test", "resources"), "Target");
45                         Directory.CreateDirectory (target_path);
46                 }
47
48                 [TearDown]
49                 public void RemoveDirectories ()
50                 {
51                         Directory.Delete (source_path, true);
52                         Directory.Delete (target_path, true);
53                 }
54
55                 [Test]
56                 public void TestCopy1 ()
57                 {
58                         Engine engine;
59                         Project project;
60                         string file_path = Path.Combine (source_path, "copy.txt");
61                         string target_file = Path.Combine (target_path, "copy.txt");
62
63                         using (File.CreateText (file_path)) { }
64
65                         string documentString = @"
66                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
67                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
68                                         <ItemGroup>
69                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
70                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
71                                         </ItemGroup>
72                                         <Target Name='1'>
73                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)' SkipUnchangedFiles='true' >
74                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
75                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
76                                                 </Copy>
77                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
78                                         </Target>
79                                 </Project>
80                         ";
81
82                         engine = new Engine (Consts.BinPath);
83                         project = engine.CreateNewProject ();
84
85                         TestMessageLogger testLogger = new TestMessageLogger ();
86                         engine.RegisterLogger (testLogger);
87
88                         project.LoadXml (documentString);
89
90                         if (!project.Build ("1")) {
91                                 testLogger.DumpMessages ();
92                                 Assert.Fail ("Build failed");
93                         }
94                         Assert.IsTrue (File.Exists (target_file), "A2");
95
96                         BuildItemGroup big = project.GetEvaluatedItemsByName ("I0");
97                         Assert.AreEqual (1, big.Count, "A3");
98                         BuildItem bi = big [0];
99                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A4");
100                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A4");
101                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A5");
102
103                         big = project.GetEvaluatedItemsByName ("I1");
104                         Assert.AreEqual (1, big.Count, "A10");
105                         bi = big [0];
106                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A11");
107                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A12");
108                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A13");
109
110                         // build again, this time files won't get copied because
111                         // of SkipUnchangedFiles=true
112                         if (!project.Build ("1")) {
113                                 testLogger.DumpMessages ();
114                                 Assert.Fail ("Build failed #2");
115                         }
116                         Assert.IsTrue (File.Exists (target_file), "A20");
117
118                         big = project.GetEvaluatedItemsByName ("I0");
119                         Assert.AreEqual (1, big.Count, "A21");
120                         bi = big [0];
121                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A22");
122                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A23");
123                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A24");
124
125                         big = project.GetEvaluatedItemsByName ("I1");
126                         Assert.AreEqual (1, big.Count, "A25");
127                         bi = big [0];
128                         Assert.AreEqual (target_file, bi.FinalItemSpec, "A26");
129                         Assert.AreEqual ("1", bi.GetMetadata ("Md"), "A27");
130                         Assert.AreEqual ("2", bi.GetMetadata ("Mde"), "A28");
131                 }
132
133                 [Test]
134                 public void TestCopy2 ()
135                 {
136                         Engine engine;
137                         Project project;
138                         string [] file_paths = new string [] {
139                                 Path.Combine (source_path, "copy1.txt"),
140                                 Path.Combine (source_path, "copy2.txt")
141                         };
142
143                         using (File.CreateText (file_paths[0])) { }
144                         using (File.CreateText (file_paths[1])) { }
145
146                         string documentString = @"
147                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
148                                         <PropertyGroup><TargetPath>" + target_path + @"</TargetPath></PropertyGroup>
149                                         <ItemGroup>
150                                                 <SFiles Include='" + file_paths [0] + @"'><Md>1</Md></SFiles>
151                                                 <SFiles Include='" + file_paths [1] + @"'><Md>2</Md></SFiles>
152                                         </ItemGroup>
153                                         <Target Name='1'>
154                                                 <Copy SourceFiles='@(SFiles)' DestinationFolder='$(TargetPath)' SkipUnchangedFiles='true' >
155                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
156                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
157                                                 </Copy>
158                                         </Target>
159                                 </Project>
160                         ";
161                         engine = new Engine (Consts.BinPath);
162                         project = engine.CreateNewProject ();
163
164                         TestMessageLogger testLogger = new TestMessageLogger ();
165                         engine.RegisterLogger (testLogger);
166
167                         project.LoadXml (documentString);
168
169                         if (!project.Build ("1")) {
170                                 testLogger.DumpMessages ();
171                                 Assert.Fail ("Build failed");
172                         }
173
174                         CheckCopyBuildItems (project, file_paths, target_path, "A1");
175
176                         // build again, this time files won't get copied because
177                         // of SkipUnchangedFiles=true
178                         if (!project.Build ("1")) {
179                                 testLogger.DumpMessages ();
180                                 Assert.Fail ("Build failed #2");
181                         }
182                         CheckCopyBuildItems (project, file_paths, target_path, "A2");
183                 }
184
185                 [Test]
186                 public void TestCopy_EmptySources () {
187                         Engine engine;
188                         Project project;
189
190                         string documentString = @"
191                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
192                                         <Target Name='1'>
193                                                 <Copy SourceFiles='@(NonExistantSourceFiles)' DestinationFolder='$(TargetPath)' SkipUnchangedFiles='true' >
194                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
195                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
196                                                 </Copy>
197                                         </Target>
198                                 </Project>
199                         ";
200                         engine = new Engine (Consts.BinPath);
201                         project = engine.CreateNewProject ();
202
203                         TestMessageLogger testLogger = new TestMessageLogger ();
204                         engine.RegisterLogger (testLogger);
205
206                         project.LoadXml (documentString);
207
208                         
209                         if (!project.Build ("1")) {
210                                 testLogger.DumpMessages ();
211                                 Assert.Fail ("Build failed");
212                         }
213                 }
214
215                 [Test]
216                 public void TestCopy_EmptyDestFolder () {
217                         Engine engine;
218                         Project project;
219
220                         string documentString = @"
221                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
222                                         <ItemGroup>
223                                                 <SFiles Include='foo.txt'><Md>1</Md></SFiles>
224                                         </ItemGroup>
225                                         <Target Name='1'>
226                                                 <Copy SourceFiles='@(SFiles)' DestinationFolder='@(NonExistant)' DestinationFiles='@(NonExistant)' SkipUnchangedFiles='true' >
227                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
228                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
229                                                 </Copy>
230                                         </Target>
231                                 </Project>
232                         ";
233                         engine = new Engine (Consts.BinPath);
234                         project = engine.CreateNewProject ();
235
236                         TestMessageLogger testLogger = new TestMessageLogger ();
237                         engine.RegisterLogger (testLogger);
238
239                         project.LoadXml (documentString);
240                         if (project.Build ("1")) {
241                                 testLogger.DumpMessages ();
242                                 Assert.Fail ("Build should have failed");
243                         }
244                 }
245
246                 [Test]
247                 public void TestCopy_ReadOnlyUpdate ()
248                 {
249                         Engine engine;
250                         Project project;
251                         string file_path = Path.Combine (source_path, "copyro.txt");
252                         string target_file = Path.Combine (target_path, "copyro.txt");                  
253
254                         using (File.CreateText (file_path)) { }
255                         
256                         string documentString = @"
257                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
258                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
259                                         <ItemGroup>
260                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
261                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
262                                         </ItemGroup>
263                                         <Target Name='1'>
264                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)' >
265                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
266                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
267                                                 </Copy>
268                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
269                                         </Target>
270                                 </Project>
271                         ";
272
273                         engine = new Engine (Consts.BinPath);
274                         project = engine.CreateNewProject ();
275
276                         TestMessageLogger testLogger = new TestMessageLogger ();
277                         engine.RegisterLogger (testLogger);
278
279                         project.LoadXml (documentString);
280
281                         if (!project.Build ("1")) {
282                                 testLogger.DumpMessages ();
283                                 Assert.Fail ("Build failed");
284                         }
285                         Assert.IsTrue (File.Exists (target_file), "A2");
286                         Assert.AreEqual (FileAttributes.Normal, File.GetAttributes (target_file), "A3");                                        
287                 }
288
289 #if NET_3_5 || NET_4_0
290                 [Test]
291                 public void TestCopy_OverwriteReadOnlyTrue ()
292                 {
293                         Engine engine;
294                         Project project;
295                         string file_path = Path.Combine (source_path, "copyro1.txt");
296                         string target_file = Path.Combine (target_path, "copyro1.txt");                 
297
298                         using (File.CreateText (file_path)) { }
299                         using (File.CreateText (target_file)) { }
300
301                         File.SetAttributes (target_file, FileAttributes.ReadOnly);
302                         Assert.AreEqual (FileAttributes.ReadOnly, File.GetAttributes (target_file), "A1");
303                         
304                         string documentString = @"
305                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
306                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
307                                         <ItemGroup>
308                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
309                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
310                                         </ItemGroup>
311                                         <Target Name='1'>
312                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)' OverwriteReadOnlyFiles='true'>
313                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
314                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
315                                                 </Copy>
316                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
317                                         </Target>
318                                 </Project>
319                         ";
320
321                         engine = new Engine (Consts.BinPath);
322                         project = engine.CreateNewProject ();
323
324                         TestMessageLogger testLogger = new TestMessageLogger ();
325                         engine.RegisterLogger (testLogger);
326
327                         project.LoadXml (documentString);
328
329                         if (!project.Build ("1")) {
330                                 testLogger.DumpMessages ();
331                                 Assert.Fail ("Build failed");
332                         }
333                         Assert.IsTrue (File.Exists (target_file), "A2");
334                         Assert.AreEqual (FileAttributes.Normal, File.GetAttributes (target_file), "A3");                                        
335                 }
336
337                 [Test]
338                 public void TestCopy_OverwriteReadOnlyFalse ()
339                 {
340                         Engine engine;
341                         Project project;
342                         string file_path = Path.Combine (source_path, "copyro2.txt");
343                         string target_file = Path.Combine (target_path, "copyro2.txt");                 
344
345                         using (File.CreateText (file_path)) { }
346                         using (File.CreateText (target_file)) { }
347
348                         File.SetAttributes (target_file, FileAttributes.ReadOnly);
349                         Assert.AreEqual (FileAttributes.ReadOnly, File.GetAttributes (target_file), "A1");
350                         
351                         string documentString = @"
352                                 <Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
353                                         <PropertyGroup><DestFile>" + target_file + @"</DestFile></PropertyGroup>
354                                         <ItemGroup>
355                                                 <SFiles Include='" + file_path + @"'><Md>1</Md></SFiles>
356                                                 <DFiles Include='$(DestFile)'><Mde>2</Mde></DFiles>
357                                         </ItemGroup>
358                                         <Target Name='1'>
359                                                 <Copy SourceFiles='@(SFiles)' DestinationFiles='@(DFiles)'>
360                                                         <Output TaskParameter='CopiedFiles' ItemName='I0'/>
361                                                         <Output TaskParameter='DestinationFiles' ItemName='I1'/>
362                                                 </Copy>
363                                                 <Message Text=""I0 : @(I0), I1: @(I1)""/>
364                                         </Target>
365                                 </Project>
366                         ";
367
368                         engine = new Engine (Consts.BinPath);
369                         project = engine.CreateNewProject ();
370
371                         TestMessageLogger testLogger = new TestMessageLogger ();
372                         engine.RegisterLogger (testLogger);
373
374                         project.LoadXml (documentString);
375
376                         // build should fail because of the readonly target file
377                         Assert.IsFalse (project.Build ("1"));
378                         
379                         File.SetAttributes (target_file, FileAttributes.Normal);
380                 }
381 #endif
382
383                 void CheckCopyBuildItems (Project project, string [] source_files, string destination_folder, string prefix)
384                 {
385                         int num = source_files.Length;
386                         for (int i = 0; i < num; i ++)
387                                 Assert.IsTrue (File.Exists (source_files [i]), prefix + " C1");
388
389                         BuildItemGroup big = project.GetEvaluatedItemsByName ("I0");
390
391                         Assert.AreEqual (num, big.Count, prefix + " C2");
392                         for (int i = 0; i < num; i++) {
393                                 string suffix = (i + 1).ToString ();
394                                 BuildItem bi = big [i];
395                                 Assert.AreEqual (Path.Combine (destination_folder, Path.GetFileName (source_files [i])),
396                                         bi.FinalItemSpec, prefix + " C3 #" + suffix);
397
398                                 Assert.AreEqual (suffix, bi.GetMetadata ("Md"), prefix + " C4 #" + suffix);
399                         }
400
401                         big = project.GetEvaluatedItemsByName ("I1");
402                         Assert.AreEqual (num, big.Count, prefix + " C6");
403                         for (int i = 0; i < num; i++) {
404                                 string suffix = (i + 1).ToString ();
405                                 BuildItem bi = big [i];
406                                 Assert.AreEqual (Path.Combine (destination_folder, Path.GetFileName (source_files [i])),
407                                         bi.FinalItemSpec, prefix + " C7 #" + suffix);
408                                 Assert.AreEqual (suffix, bi.GetMetadata ("Md"), prefix + " C8 #" + suffix);
409                         }
410                  }
411         }
412 }