-
Notifications
You must be signed in to change notification settings - Fork 585
Expand file tree
/
Copy pathElementLookupTests.cs
More file actions
192 lines (158 loc) · 6.48 KB
/
ElementLookupTests.cs
File metadata and controls
192 lines (158 loc) · 6.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using DocumentFormat.OpenXml.Features;
using DocumentFormat.OpenXml.Framework.Metadata;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Tests;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using Xunit;
using static DocumentFormat.OpenXml.Framework.Tests.TestUtility;
namespace DocumentFormat.OpenXml.Framework.Tests
{
public class ElementLookupTests
{
private readonly ITestOutputHelper _output;
public ElementLookupTests(ITestOutputHelper output)
{
_output = output;
}
[Fact]
public void BuiltInOpenXmlElements()
{
var elements = GetBuiltIn();
#if DEBUG
_output.WriteObjectToTempFile("built in elements", elements);
#endif
var expected = Deserialize<LookupData[]>("ElementChildren.json");
var actual = GetBuiltIn().ToArray();
Assert.Equal(expected, actual);
}
[Fact]
public void VerifyTypedRootsCanBeCreatedWord()
{
// Arrange
using var word = WordprocessingDocument.Create(new MemoryStream(), WordprocessingDocumentType.Document);
using var excel = SpreadsheetDocument.Create(new MemoryStream(), SpreadsheetDocumentType.Workbook);
using var ppt = PresentationDocument.Create(new MemoryStream(), PresentationDocumentType.Presentation);
var feature = new CompositeRootElementFeature(word, excel, ppt);
var allTypedParts = typeof(WordprocessingDocument).Assembly
.GetTypes()
.Where(t => !t.IsAbstract && typeof(OpenXmlPartRootElement).IsAssignableFrom(t))
.ToList();
Assert.Equal(103, allTypedParts.Count);
// Act/Assert
foreach (var rootType in allTypedParts)
{
var root = ((OpenXmlElement)Activator.CreateInstance(rootType))!;
Assert.True(feature.TryCreate(root.QName, out var created));
Assert.IsType(rootType, created);
}
}
[Fact]
public void DumpBuiltInOpenXmlElements()
{
// This should align with the text in ElementChildren.json
var expected = Serialize(GetBuiltIn());
Assert.NotNull(expected);
}
private static readonly Type[] TypesFromFramework = new[]
{
typeof(OpenXmlPartRootElement),
typeof(AlternateContent),
typeof(AlternateContentChoice),
typeof(AlternateContentFallback),
typeof(OpenXmlMiscNode),
typeof(OpenXmlUnknownElement),
};
private static IEnumerable<LookupData> GetBuiltIn()
{
return typeof(SpreadsheetDocument).GetTypeInfo().Assembly.GetTypes()
.Where(t => !t.GetTypeInfo().IsAbstract && typeof(OpenXmlElement).GetTypeInfo().IsAssignableFrom(t))
.Concat(TypesFromFramework)
.Distinct()
.OrderBy(type => type.FullName, StringComparer.Ordinal)
.Select(type => new LookupData(type));
}
private sealed class CompositeRootElementFeature : IRootElementFeature
{
private readonly IRootElementFeature[] _features;
public CompositeRootElementFeature(params OpenXmlPackage[] package)
{
_features = package.Select(p => p.Features.GetRequired<IRootElementFeature>()).ToArray();
}
public bool TryCreate(in OpenXmlQualifiedName qname, [NotNullWhen(true)] out OpenXmlElement element)
{
foreach (var feature in _features)
{
if (feature.TryCreate(qname, out element))
{
return true;
}
}
element = null;
return false;
}
}
private class LookupData : IEquatable<LookupData>
{
public LookupData()
{
}
public LookupData(Type type)
{
Element = type.FullName;
ElementFactoryCollection GetLookup()
{
if (type.GetConstructor(Cached.Array<Type>()) is not null)
{
var instance = (OpenXmlElement)Activator.CreateInstance(type);
return instance.Metadata.Children;
}
else
{
return ElementFactoryCollection.Empty;
}
}
Children = GetLookup().Elements.Select(t => new ChildData
{
Name = t.QName.Name,
Namespace = t.QName.Namespace.Uri,
});
}
public string Element { get; set; }
public IEnumerable<ChildData> Children { get; set; }
public override bool Equals(object obj) => Equals(obj as LookupData);
public bool Equals(LookupData other)
{
if (other is null)
{
return false;
}
if (!string.Equals(Element, other.Element, StringComparison.Ordinal) || !Children.SequenceEqual(other.Children))
{
System.Diagnostics.Debugger.Break();
}
return string.Equals(Element, other.Element, StringComparison.Ordinal)
&& Children.SequenceEqual(other.Children);
}
public override int GetHashCode() => throw new NotImplementedException();
public class ChildData : IEquatable<ChildData>
{
public string Name { get; set; }
public string Namespace { get; set; }
public bool Equals(ChildData other)
{
return string.Equals(Name, other.Name, StringComparison.Ordinal)
&& string.Equals(Namespace, other.Namespace, StringComparison.Ordinal);
}
public override int GetHashCode() => throw new NotImplementedException();
public override bool Equals(object obj) => Equals(obj as ChildData);
}
}
}
}