@joebigelow / wix-1 / commits / c4497aa7

Support instance transforms

Rob Mensching committed May 23, 2020 at 01:57 UTC c4497aa78b2d85b2613af64311bf282756aff43a
3 files changed +297 -243
src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs
+2 -241
@@ -373,9 +373,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
373 }
374 else // we can create instance transforms since Component Guids are set.
375 {
376 -#if TODO_FIX_INSTANCE_TRANSFORM
377 - this.CreateInstanceTransforms(this.Output);
378 -#endif
376 + var command = new CreateInstanceTransformsCommand(section, output, tableDefinitions, this.BackendHelper);
377 + command.Execute();
378 }
379
380 #if TODO_FINISH_UPDATE
@@ -640,244 +639,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind
639 }
640 #endif
641
643 -
644 -#if TODO_FIX_INSTANCE_TRANSFORM
645 - /// <summary>
646 - /// Creates instance transform substorages in the output.
647 - /// </summary>
648 - /// <param name="output">Output containing instance transform definitions.</param>
649 - private void CreateInstanceTransforms(Output output)
650 - {
651 - // Create and add substorages for instance transforms.
652 - Table wixInstanceTransformsTable = output.Tables["WixInstanceTransforms"];
653 - if (null != wixInstanceTransformsTable && 0 <= wixInstanceTransformsTable.Rows.Count)
654 - {
655 - string targetProductCode = null;
656 - string targetUpgradeCode = null;
657 - string targetProductVersion = null;
658 -
659 - Table targetSummaryInformationTable = output.Tables["_SummaryInformation"];
660 - Table targetPropertyTable = output.Tables["Property"];
661 -
662 - // Get the data from target database
663 - foreach (Row propertyRow in targetPropertyTable.Rows)
664 - {
665 - if ("ProductCode" == (string)propertyRow[0])
666 - {
667 - targetProductCode = (string)propertyRow[1];
668 - }
669 - else if ("ProductVersion" == (string)propertyRow[0])
670 - {
671 - targetProductVersion = (string)propertyRow[1];
672 - }
673 - else if ("UpgradeCode" == (string)propertyRow[0])
674 - {
675 - targetUpgradeCode = (string)propertyRow[1];
676 - }
677 - }
678 -
679 - // Index the Instance Component Rows.
680 - Dictionary<string, ComponentRow> instanceComponentGuids = new Dictionary<string, ComponentRow>();
681 - Table targetInstanceComponentTable = output.Tables["WixInstanceComponent"];
682 - if (null != targetInstanceComponentTable && 0 < targetInstanceComponentTable.Rows.Count)
683 - {
684 - foreach (Row row in targetInstanceComponentTable.Rows)
685 - {
686 - // Build up all the instances, we'll get the Components rows from the real Component table.
687 - instanceComponentGuids.Add((string)row[0], null);
688 - }
689 -
690 - Table targetComponentTable = output.Tables["Component"];
691 - foreach (ComponentRow componentRow in targetComponentTable.Rows)
692 - {
693 - string component = (string)componentRow[0];
694 - if (instanceComponentGuids.ContainsKey(component))
695 - {
696 - instanceComponentGuids[component] = componentRow;
697 - }
698 - }
699 - }
700 -
701 - // Generate the instance transforms
702 - foreach (Row instanceRow in wixInstanceTransformsTable.Rows)
703 - {
704 - string instanceId = (string)instanceRow[0];
705 -
706 - Output instanceTransform = new Output(instanceRow.SourceLineNumbers);
707 - instanceTransform.Type = OutputType.Transform;
708 - instanceTransform.Codepage = output.Codepage;
709 -
710 - Table instanceSummaryInformationTable = instanceTransform.EnsureTable(this.TableDefinitions["_SummaryInformation"]);
711 - string targetPlatformAndLanguage = null;
712 -
713 - foreach (Row summaryInformationRow in targetSummaryInformationTable.Rows)
714 - {
715 - if (7 == (int)summaryInformationRow[0]) // PID_TEMPLATE
716 - {
717 - targetPlatformAndLanguage = (string)summaryInformationRow[1];
718 - }
719 -
720 - // Copy the row's data to the transform.
721 - Row copyOfSummaryRow = instanceSummaryInformationTable.CreateRow(null);
722 - copyOfSummaryRow[0] = summaryInformationRow[0];
723 - copyOfSummaryRow[1] = summaryInformationRow[1];
724 - }
725 -
726 - // Modify the appropriate properties.
727 - Table propertyTable = instanceTransform.EnsureTable(this.TableDefinitions["Property"]);
728 -
729 - // Change the ProductCode property
730 - string productCode = (string)instanceRow[2];
731 - if ("*" == productCode)
732 - {
733 - productCode = Common.GenerateGuid();
734 - }
735 -
736 - Row productCodeRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers);
737 - productCodeRow.Operation = RowOperation.Modify;
738 - productCodeRow.Fields[1].Modified = true;
739 - productCodeRow[0] = "ProductCode";
740 - productCodeRow[1] = productCode;
741 -
742 - // Change the instance property
743 - Row instanceIdRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers);
744 - instanceIdRow.Operation = RowOperation.Modify;
745 - instanceIdRow.Fields[1].Modified = true;
746 - instanceIdRow[0] = (string)instanceRow[1];
747 - instanceIdRow[1] = instanceId;
748 -
749 - if (null != instanceRow[3])
750 - {
751 - // Change the ProductName property
752 - Row productNameRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers);
753 - productNameRow.Operation = RowOperation.Modify;
754 - productNameRow.Fields[1].Modified = true;
755 - productNameRow[0] = "ProductName";
756 - productNameRow[1] = (string)instanceRow[3];
757 - }
758 -
759 - if (null != instanceRow[4])
760 - {
761 - // Change the UpgradeCode property
762 - Row upgradeCodeRow = propertyTable.CreateRow(instanceRow.SourceLineNumbers);
763 - upgradeCodeRow.Operation = RowOperation.Modify;
764 - upgradeCodeRow.Fields[1].Modified = true;
765 - upgradeCodeRow[0] = "UpgradeCode";
766 - upgradeCodeRow[1] = instanceRow[4];
767 -
768 - // Change the Upgrade table
769 - Table targetUpgradeTable = output.Tables["Upgrade"];
770 - if (null != targetUpgradeTable && 0 <= targetUpgradeTable.Rows.Count)
771 - {
772 - string upgradeId = (string)instanceRow[4];
773 - Table upgradeTable = instanceTransform.EnsureTable(this.TableDefinitions["Upgrade"]);
774 - foreach (Row row in targetUpgradeTable.Rows)
775 - {
776 - // In case they are upgrading other codes to this new product, leave the ones that don't match the
777 - // Product.UpgradeCode intact.
778 - if (targetUpgradeCode == (string)row[0])
779 - {
780 - Row upgradeRow = upgradeTable.CreateRow(null);
781 - upgradeRow.Operation = RowOperation.Add;
782 - upgradeRow.Fields[0].Modified = true;
783 - // I was hoping to be able to RowOperation.Modify, but that didn't appear to function.
784 - // upgradeRow.Fields[0].PreviousData = (string)row[0];
785 -
786 - // Inserting a new Upgrade record with the updated UpgradeCode
787 - upgradeRow[0] = upgradeId;
788 - upgradeRow[1] = row[1];
789 - upgradeRow[2] = row[2];
790 - upgradeRow[3] = row[3];
791 - upgradeRow[4] = row[4];
792 - upgradeRow[5] = row[5];
793 - upgradeRow[6] = row[6];
794 -
795 - // Delete the old row
796 - Row upgradeRemoveRow = upgradeTable.CreateRow(null);
797 - upgradeRemoveRow.Operation = RowOperation.Delete;
798 - upgradeRemoveRow[0] = row[0];
799 - upgradeRemoveRow[1] = row[1];
800 - upgradeRemoveRow[2] = row[2];
801 - upgradeRemoveRow[3] = row[3];
802 - upgradeRemoveRow[4] = row[4];
803 - upgradeRemoveRow[5] = row[5];
804 - upgradeRemoveRow[6] = row[6];
805 - }
806 - }
807 - }
808 - }
809 -
810 - // If there are instance Components generate new GUIDs for them.
811 - if (0 < instanceComponentGuids.Count)
812 - {
813 - Table componentTable = instanceTransform.EnsureTable(this.TableDefinitions["Component"]);
814 - foreach (ComponentRow targetComponentRow in instanceComponentGuids.Values)
815 - {
816 - string guid = targetComponentRow.Guid;
817 - if (!String.IsNullOrEmpty(guid))
818 - {
819 - Row instanceComponentRow = componentTable.CreateRow(targetComponentRow.SourceLineNumbers);
820 - instanceComponentRow.Operation = RowOperation.Modify;
821 - instanceComponentRow.Fields[1].Modified = true;
822 - instanceComponentRow[0] = targetComponentRow[0];
823 - instanceComponentRow[1] = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, String.Concat(guid, instanceId)).ToString("B").ToUpper(CultureInfo.InvariantCulture);
824 - instanceComponentRow[2] = targetComponentRow[2];
825 - instanceComponentRow[3] = targetComponentRow[3];
826 - instanceComponentRow[4] = targetComponentRow[4];
827 - instanceComponentRow[5] = targetComponentRow[5];
828 - }
829 - }
830 - }
831 -
832 - // Update the summary information
833 - Hashtable summaryRows = new Hashtable(instanceSummaryInformationTable.Rows.Count);
834 - foreach (Row row in instanceSummaryInformationTable.Rows)
835 - {
836 - summaryRows[row[0]] = row;
837 -
838 - if ((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage == (int)row[0])
839 - {
840 - row[1] = targetPlatformAndLanguage;
841 - }
842 - else if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0])
843 - {
844 - row[1] = String.Concat(targetProductCode, targetProductVersion, ';', productCode, targetProductVersion, ';', targetUpgradeCode);
845 - }
846 - else if ((int)SummaryInformation.Transform.ValidationFlags == (int)row[0])
847 - {
848 - row[1] = 0;
849 - }
850 - else if ((int)SummaryInformation.Transform.Security == (int)row[0])
851 - {
852 - row[1] = "4";
853 - }
854 - }
855 -
856 - if (!summaryRows.Contains((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage))
857 - {
858 - Row summaryRow = instanceSummaryInformationTable.CreateRow(null);
859 - summaryRow[0] = (int)SummaryInformation.Transform.UpdatedPlatformAndLanguage;
860 - summaryRow[1] = targetPlatformAndLanguage;
861 - }
862 - else if (!summaryRows.Contains((int)SummaryInformation.Transform.ValidationFlags))
863 - {
864 - Row summaryRow = instanceSummaryInformationTable.CreateRow(null);
865 - summaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags;
866 - summaryRow[1] = "0";
867 - }
868 - else if (!summaryRows.Contains((int)SummaryInformation.Transform.Security))
869 - {
870 - Row summaryRow = instanceSummaryInformationTable.CreateRow(null);
871 - summaryRow[0] = (int)SummaryInformation.Transform.Security;
872 - summaryRow[1] = "4";
873 - }
874 -
875 - output.SubStorages.Add(new SubStorage(instanceId, instanceTransform));
876 - }
877 - }
878 - }
879 -#endif
880 -
642 /// <summary>
643 /// Validate that there are no duplicate GUIDs in the output.
644 /// </summary>
src/WixToolset.Core.WindowsInstaller/Bind/CreateInstanceTransformsCommand.cs new
+260
@@ -0,0 +1,260 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolset.Core.WindowsInstaller.Bind
4 +{
5 + using System;
6 + using System.Collections.Generic;
7 + using System.Linq;
8 + using WixToolset.Core.WindowsInstaller.Msi;
9 + using WixToolset.Data;
10 + using WixToolset.Data.Tuples;
11 + using WixToolset.Data.WindowsInstaller;
12 + using WixToolset.Data.WindowsInstaller.Rows;
13 + using WixToolset.Extensibility.Services;
14 +
15 + internal class CreateInstanceTransformsCommand
16 + {
17 + public CreateInstanceTransformsCommand(IntermediateSection section, WindowsInstallerData output, TableDefinitionCollection tableDefinitions, IBackendHelper backendHelper)
18 + {
19 + this.Section = section;
20 + this.Output = output;
21 + this.TableDefinitions = tableDefinitions;
22 + this.BackendHelper = backendHelper;
23 + }
24 +
25 + private IntermediateSection Section { get; }
26 +
27 + private WindowsInstallerData Output { get; }
28 +
29 + public TableDefinitionCollection TableDefinitions { get; }
30 +
31 + private IBackendHelper BackendHelper { get; }
32 +
33 + public void Execute()
34 + {
35 + // Create and add substorages for instance transforms.
36 + var wixInstanceTransformsTuples = this.Section.Tuples.OfType<WixInstanceTransformsTuple>();
37 +
38 + if (wixInstanceTransformsTuples.Any())
39 + {
40 + string targetProductCode = null;
41 + string targetUpgradeCode = null;
42 + string targetProductVersion = null;
43 +
44 + var targetSummaryInformationTable = this.Output.Tables["_SummaryInformation"];
45 + var targetPropertyTable = this.Output.Tables["Property"];
46 +
47 + // Get the data from target database
48 + foreach (var propertyRow in targetPropertyTable.Rows)
49 + {
50 + if ("ProductCode" == (string)propertyRow[0])
51 + {
52 + targetProductCode = (string)propertyRow[1];
53 + }
54 + else if ("ProductVersion" == (string)propertyRow[0])
55 + {
56 + targetProductVersion = (string)propertyRow[1];
57 + }
58 + else if ("UpgradeCode" == (string)propertyRow[0])
59 + {
60 + targetUpgradeCode = (string)propertyRow[1];
61 + }
62 + }
63 +
64 + // Index the Instance Component Rows, we'll get the Components rows from the real Component table.
65 + var targetInstanceComponentTable = this.Section.Tuples.OfType<WixInstanceComponentTuple>();
66 + var instanceComponentGuids = targetInstanceComponentTable.ToDictionary(t => t.Id.Id, t => (ComponentRow)null);
67 +
68 + if (instanceComponentGuids.Any())
69 + {
70 + var targetComponentTable = this.Output.Tables["Component"];
71 + foreach (ComponentRow componentRow in targetComponentTable.Rows)
72 + {
73 + var component = (string)componentRow[0];
74 + if (instanceComponentGuids.ContainsKey(component))
75 + {
76 + instanceComponentGuids[component] = componentRow;
77 + }
78 + }
79 + }
80 +
81 + // Generate the instance transforms
82 + foreach (var instanceTuple in wixInstanceTransformsTuples)
83 + {
84 + var instanceId = instanceTuple.Id.Id;
85 +
86 + var instanceTransform = new WindowsInstallerData(instanceTuple.SourceLineNumbers);
87 + instanceTransform.Type = OutputType.Transform;
88 + instanceTransform.Codepage = this.Output.Codepage;
89 +
90 + var instanceSummaryInformationTable = instanceTransform.EnsureTable(this.TableDefinitions["_SummaryInformation"]);
91 + string targetPlatformAndLanguage = null;
92 +
93 + foreach (var summaryInformationRow in targetSummaryInformationTable.Rows)
94 + {
95 + if (7 == (int)summaryInformationRow[0]) // PID_TEMPLATE
96 + {
97 + targetPlatformAndLanguage = (string)summaryInformationRow[1];
98 + }
99 +
100 + // Copy the row's data to the transform.
101 + var copyOfSummaryRow = instanceSummaryInformationTable.CreateRow(summaryInformationRow.SourceLineNumbers);
102 + copyOfSummaryRow[0] = summaryInformationRow[0];
103 + copyOfSummaryRow[1] = summaryInformationRow[1];
104 + }
105 +
106 + // Modify the appropriate properties.
107 + var propertyTable = instanceTransform.EnsureTable(this.TableDefinitions["Property"]);
108 +
109 + // Change the ProductCode property
110 + var productCode = instanceTuple.ProductCode;
111 + if ("*" == productCode)
112 + {
113 + productCode = Common.GenerateGuid();
114 + }
115 +
116 + var productCodeRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
117 + productCodeRow.Operation = RowOperation.Modify;
118 + productCodeRow.Fields[1].Modified = true;
119 + productCodeRow[0] = "ProductCode";
120 + productCodeRow[1] = productCode;
121 +
122 + // Change the instance property
123 + var instanceIdRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
124 + instanceIdRow.Operation = RowOperation.Modify;
125 + instanceIdRow.Fields[1].Modified = true;
126 + instanceIdRow[0] = instanceTuple.PropertyId;
127 + instanceIdRow[1] = instanceId;
128 +
129 + if (!String.IsNullOrEmpty(instanceTuple.ProductName))
130 + {
131 + // Change the ProductName property
132 + var productNameRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
133 + productNameRow.Operation = RowOperation.Modify;
134 + productNameRow.Fields[1].Modified = true;
135 + productNameRow[0] = "ProductName";
136 + productNameRow[1] = instanceTuple.ProductName;
137 + }
138 +
139 + if (!String.IsNullOrEmpty(instanceTuple.UpgradeCode))
140 + {
141 + // Change the UpgradeCode property
142 + var upgradeCodeRow = propertyTable.CreateRow(instanceTuple.SourceLineNumbers);
143 + upgradeCodeRow.Operation = RowOperation.Modify;
144 + upgradeCodeRow.Fields[1].Modified = true;
145 + upgradeCodeRow[0] = "UpgradeCode";
146 + upgradeCodeRow[1] = instanceTuple.UpgradeCode;
147 +
148 + // Change the Upgrade table
149 + var targetUpgradeTable = this.Output.Tables["Upgrade"];
150 + if (null != targetUpgradeTable && 0 <= targetUpgradeTable.Rows.Count)
151 + {
152 + var upgradeId = instanceTuple.UpgradeCode;
153 + var upgradeTable = instanceTransform.EnsureTable(this.TableDefinitions["Upgrade"]);
154 + foreach (var row in targetUpgradeTable.Rows)
155 + {
156 + // In case they are upgrading other codes to this new product, leave the ones that don't match the
157 + // Product.UpgradeCode intact.
158 + if (targetUpgradeCode == (string)row[0])
159 + {
160 + var upgradeRow = upgradeTable.CreateRow(row.SourceLineNumbers);
161 + upgradeRow.Operation = RowOperation.Add;
162 + upgradeRow.Fields[0].Modified = true;
163 + // I was hoping to be able to RowOperation.Modify, but that didn't appear to function.
164 + // upgradeRow.Fields[0].PreviousData = (string)row[0];
165 +
166 + // Inserting a new Upgrade record with the updated UpgradeCode
167 + upgradeRow[0] = upgradeId;
168 + upgradeRow[1] = row[1];
169 + upgradeRow[2] = row[2];
170 + upgradeRow[3] = row[3];
171 + upgradeRow[4] = row[4];
172 + upgradeRow[5] = row[5];
173 + upgradeRow[6] = row[6];
174 +
175 + // Delete the old row
176 + var upgradeRemoveRow = upgradeTable.CreateRow(row.SourceLineNumbers);
177 + upgradeRemoveRow.Operation = RowOperation.Delete;
178 + upgradeRemoveRow[0] = row[0];
179 + upgradeRemoveRow[1] = row[1];
180 + upgradeRemoveRow[2] = row[2];
181 + upgradeRemoveRow[3] = row[3];
182 + upgradeRemoveRow[4] = row[4];
183 + upgradeRemoveRow[5] = row[5];
184 + upgradeRemoveRow[6] = row[6];
185 + }
186 + }
187 + }
188 + }
189 +
190 + // If there are instance Components generate new GUIDs for them.
191 + if (0 < instanceComponentGuids.Count)
192 + {
193 + var componentTable = instanceTransform.EnsureTable(this.TableDefinitions["Component"]);
194 + foreach (var targetComponentRow in instanceComponentGuids.Values)
195 + {
196 + var guid = targetComponentRow.Guid;
197 + if (!String.IsNullOrEmpty(guid))
198 + {
199 + var instanceComponentRow = componentTable.CreateRow(targetComponentRow.SourceLineNumbers);
200 + instanceComponentRow.Operation = RowOperation.Modify;
201 + instanceComponentRow.Fields[1].Modified = true;
202 + instanceComponentRow[0] = targetComponentRow[0];
203 + instanceComponentRow[1] = this.BackendHelper.CreateGuid(BindDatabaseCommand.WixComponentGuidNamespace, String.Concat(guid, instanceId));
204 + instanceComponentRow[2] = targetComponentRow[2];
205 + instanceComponentRow[3] = targetComponentRow[3];
206 + instanceComponentRow[4] = targetComponentRow[4];
207 + instanceComponentRow[5] = targetComponentRow[5];
208 + }
209 + }
210 + }
211 +
212 + // Update the summary information
213 + var summaryRows = new Dictionary<int, Row>(instanceSummaryInformationTable.Rows.Count);
214 + foreach (var row in instanceSummaryInformationTable.Rows)
215 + {
216 + summaryRows[(int)row[0]] = row;
217 +
218 + if ((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage == (int)row[0])
219 + {
220 + row[1] = targetPlatformAndLanguage;
221 + }
222 + else if ((int)SummaryInformation.Transform.ProductCodes == (int)row[0])
223 + {
224 + row[1] = String.Concat(targetProductCode, targetProductVersion, ';', productCode, targetProductVersion, ';', targetUpgradeCode);
225 + }
226 + else if ((int)SummaryInformation.Transform.ValidationFlags == (int)row[0])
227 + {
228 + row[1] = 0;
229 + }
230 + else if ((int)SummaryInformation.Transform.Security == (int)row[0])
231 + {
232 + row[1] = "4";
233 + }
234 + }
235 +
236 + if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.UpdatedPlatformAndLanguage))
237 + {
238 + var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers);
239 + summaryRow[0] = (int)SummaryInformation.Transform.UpdatedPlatformAndLanguage;
240 + summaryRow[1] = targetPlatformAndLanguage;
241 + }
242 + else if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.ValidationFlags))
243 + {
244 + var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers);
245 + summaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags;
246 + summaryRow[1] = "0";
247 + }
248 + else if (!summaryRows.ContainsKey((int)SummaryInformation.Transform.Security))
249 + {
250 + var summaryRow = instanceSummaryInformationTable.CreateRow(instanceTuple.SourceLineNumbers);
251 + summaryRow[0] = (int)SummaryInformation.Transform.Security;
252 + summaryRow[1] = "4";
253 + }
254 +
255 + this.Output.SubStorages.Add(new SubStorage(instanceId, instanceTransform));
256 + }
257 + }
258 + }
259 + }
260 +}
src/test/WixToolsetTest.CoreIntegration/MsiFixture.cs
+35 -2
@@ -790,7 +790,7 @@ namespace WixToolsetTest.CoreIntegration
790 }
791 }
792
793 - [Fact(Skip = "Not implemented yet.")]
793 + [Fact]
794 public void CanBuildInstanceTransform()
795 {
796 var folder = TestData.Get(@"TestData\InstanceTransform");
@@ -813,7 +813,30 @@ namespace WixToolsetTest.CoreIntegration
813 result.AssertSuccess();
814
815 var output = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"), false);
816 - Assert.NotEmpty(output.SubStorages);
816 + var substorage = output.SubStorages.Single();
817 + Assert.Equal("I1", substorage.Name);
818 +
819 + var data = substorage.Data;
820 + Assert.Equal(new[]
821 + {
822 + "_SummaryInformation",
823 + "Property",
824 + "Upgrade"
825 + }, data.Tables.Select(t => t.Name).ToArray());
826 +
827 + Assert.Equal(new[]
828 + {
829 + "INSTANCEPROPERTY\tI1",
830 + "ProductName\tMsiPackage (Instance 1)",
831 + }, JoinRows(data.Tables["Property"]));
832 +
833 + Assert.Equal(new[]
834 + {
835 + "{047730A5-30FE-4A62-A520-DA9381B8226A}\t\t1.0.0.0\t1033\t1\t\tWIX_UPGRADE_DETECTED",
836 + "{047730A5-30FE-4A62-A520-DA9381B8226A}\t\t1.0.0.0\t1033\t1\t0\t0",
837 + "{047730A5-30FE-4A62-A520-DA9381B8226A}\t1.0.0.0\t\t1033\t2\t\tWIX_DOWNGRADE_DETECTED",
838 + "{047730A5-30FE-4A62-A520-DA9381B8226A}\t1.0.0.0\t\t1033\t2\t0\t0"
839 + }, JoinRows(data.Tables["Upgrade"]));
840 }
841 }
842
@@ -850,5 +873,15 @@ namespace WixToolsetTest.CoreIntegration
873 Assert.False(File.Exists(msiPath));
874 }
875 }
876 +
877 + private static string[] JoinRows(Table table)
878 + {
879 + return table.Rows.Select(r => JoinFields(r.Fields)).ToArray();
880 +
881 + string JoinFields(Field[] fields)
882 + {
883 + return String.Join('\t', fields.Select(f => f.ToString()));
884 + }
885 + }
886 }
887 }