|
| 1 | +using ILSourceParser.Common; |
| 2 | +using ILSourceParser.Syntax; |
| 3 | +using ILSourceParser.Utilities; |
| 4 | +using Sprache; |
| 5 | + |
| 6 | +namespace ILSourceParser.Tests; |
| 7 | + |
| 8 | +public class AssemblyTests |
| 9 | +{ |
| 10 | + private static readonly byte[] s_complexCustomAttributePermissionSetDescendantByteData = |
| 11 | + [ |
| 12 | + 0x2e, 0x01, 0x80, 0x8a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x53, 0x65, 0x63, |
| 13 | + 0x75, 0x72, 0x69, 0x74, 0x79, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, |
| 14 | + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x65, |
| 15 | + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, |
| 16 | + 0x75, 0x74, 0x65, 0x2c, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x52, 0x75, |
| 17 | + 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, |
| 18 | + 0x3d, 0x38, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x43, 0x75, 0x6c, 0x74, |
| 19 | + 0x75, 0x72, 0x65, 0x3d, 0x6e, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6c, 0x2c, 0x20, 0x50, |
| 20 | + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x3d, |
| 21 | + 0x62, 0x30, 0x33, 0x66, 0x35, 0x66, 0x37, 0x66, 0x31, 0x31, 0x64, 0x35, 0x30, 0x61, |
| 22 | + 0x33, 0x61, 0x15, 0x01, 0x54, 0x02, 0x10, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, |
| 23 | + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x01 |
| 24 | + ]; |
| 25 | + |
| 26 | + [Fact] |
| 27 | + public void Simple() |
| 28 | + { |
| 29 | + var parser = new Parser(); |
| 30 | + var asmParser = parser.ParseAssemblyDeclaration(); |
| 31 | + var result = asmParser.Parse(@".assembly extern System.Private.CoreLib |
| 32 | +{ |
| 33 | + .line 123 |
| 34 | +}"); |
| 35 | + |
| 36 | + Assert.True(result.IsExtern); |
| 37 | + Assert.Equal("System.Private.CoreLib", result.AssemblyName); |
| 38 | + Assert.Single(result.DescendantNodes); |
| 39 | + |
| 40 | + Assert.True(result.DescendantNodes.ElementAt(0) is LineDirectiveSyntax); |
| 41 | + } |
| 42 | + |
| 43 | + [Fact] |
| 44 | + public void Complex() |
| 45 | + { |
| 46 | + var parser = new Parser(); |
| 47 | + var asmParser = parser.ParseAssemblyDeclaration(); |
| 48 | + var result = asmParser.Parse(@".assembly _ |
| 49 | +{ |
| 50 | + .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( |
| 51 | + 01 00 08 00 00 00 00 00 |
| 52 | + ) |
| 53 | + .custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( |
| 54 | + 01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78 |
| 55 | + 63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01 |
| 56 | + ) |
| 57 | + .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( |
| 58 | + 01 00 02 00 00 00 00 00 |
| 59 | + ) |
| 60 | + .permissionset reqmin = ( |
| 61 | + 2e 01 80 8a 53 79 73 74 65 6d 2e 53 65 63 75 72 |
| 62 | + 69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e |
| 63 | + 53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69 |
| 64 | + 6f 6e 41 74 74 72 69 62 75 74 65 2c 20 53 79 73 |
| 65 | + 74 65 6d 2e 52 75 6e 74 69 6d 65 2c 20 56 65 72 |
| 66 | + 73 69 6f 6e 3d 38 2e 30 2e 30 2e 30 2c 20 43 75 |
| 67 | + 6c 74 75 72 65 3d 6e 65 75 74 72 61 6c 2c 20 50 |
| 68 | + 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e 3d 62 30 |
| 69 | + 33 66 35 66 37 66 31 31 64 35 30 61 33 61 15 01 |
| 70 | + 54 02 10 53 6b 69 70 56 65 72 69 66 69 63 61 74 |
| 71 | + 69 6f 6e 01 |
| 72 | + ) |
| 73 | + .hash algorithm 0x00008004 // SHA1 |
| 74 | + .ver 0:0:0:0 |
| 75 | +}"); |
| 76 | + |
| 77 | + Assert.False(result.IsExtern); |
| 78 | + Assert.Equal("_", result.AssemblyName); |
| 79 | + Assert.Equal(7, result.DescendantNodes.Count()); // Don't forget that we also have an inline comment with text "SHA1" next to ".hash algorithm" node. |
| 80 | + |
| 81 | + Assert.True(result.DescendantNodes.ElementAt(0) is CustomAttributeSyntax); |
| 82 | + Assert.True(result.DescendantNodes.ElementAt(1) is CustomAttributeSyntax); |
| 83 | + Assert.True(result.DescendantNodes.ElementAt(2) is CustomAttributeSyntax); |
| 84 | + Assert.True(result.DescendantNodes.ElementAt(3) is PermissionSetSyntax); |
| 85 | + Assert.True(result.DescendantNodes.ElementAt(4) is HashAlgorithmSyntax); |
| 86 | + Assert.True(result.DescendantNodes.ElementAt(5) is InlineCommentSyntax); |
| 87 | + Assert.True(result.DescendantNodes.ElementAt(6) is VerDirectiveSyntax); |
| 88 | + |
| 89 | + TestElement1(); |
| 90 | + TestElement2(); |
| 91 | + TestElement3(); |
| 92 | + TestElement4(); |
| 93 | + TestElement5(); |
| 94 | + TestElement6(); |
| 95 | + TestElement7(); |
| 96 | + |
| 97 | + void TestElement1() |
| 98 | + { |
| 99 | + var element = (CustomAttributeSyntax)result.DescendantNodes.ElementAt(0); |
| 100 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.TypeReference is NonGenericTypeReferenceSyntax); |
| 101 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.MethodName == ".ctor"); |
| 102 | + Assert.True(((NonGenericTypeReferenceSyntax)element.AttributeConstructorTarget.MethodInvocation.TypeReference).ClassName == "System.Runtime.CompilerServices.CompilationRelaxationsAttribute"); |
| 103 | + Assert.Single(element.AttributeConstructorTarget.MethodInvocation.Arguments.Arguments); |
| 104 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.Arguments.Arguments.ElementAt(0) is PredefinedTypeSyntax predefinedType |
| 105 | + && predefinedType.Kind == PredefinedTypeKind.Int32 |
| 106 | + && predefinedType.TypeName == "int32"); |
| 107 | + Assert.True( |
| 108 | + Enumerable.SequenceEqual( |
| 109 | + element.GetRawBytes(), |
| 110 | + new byte[] { 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 } |
| 111 | + ) |
| 112 | + ); |
| 113 | + } |
| 114 | + |
| 115 | + void TestElement2() |
| 116 | + { |
| 117 | + var element = (CustomAttributeSyntax)result.DescendantNodes.ElementAt(1); |
| 118 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.TypeReference is NonGenericTypeReferenceSyntax); |
| 119 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.MethodName == ".ctor"); |
| 120 | + Assert.True(((NonGenericTypeReferenceSyntax)element.AttributeConstructorTarget.MethodInvocation.TypeReference).ClassName == "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute"); |
| 121 | + Assert.Empty(element.AttributeConstructorTarget.MethodInvocation.Arguments.Arguments); |
| 122 | + Assert.True( |
| 123 | + Enumerable.SequenceEqual( |
| 124 | + element.GetRawBytes(), |
| 125 | + new byte[] |
| 126 | + { |
| 127 | + 0x01, 0x00, 0x01, 0x00, 0x54, 0x02, 0x16, 0x57, |
| 128 | + 0x72, 0x61, 0x70, 0x4e, 0x6f, 0x6e, 0x45, 0x78, 0x63, 0x65, |
| 129 | + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x68, 0x72, 0x6f, 0x77, |
| 130 | + 0x73, 0x01 |
| 131 | + } |
| 132 | + ) |
| 133 | + ); |
| 134 | + } |
| 135 | + |
| 136 | + void TestElement3() |
| 137 | + { |
| 138 | + var element = (CustomAttributeSyntax)result.DescendantNodes.ElementAt(2); |
| 139 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.TypeReference is NonGenericTypeReferenceSyntax); |
| 140 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.MethodName == ".ctor"); |
| 141 | + Assert.Equal("System.Runtime", ((NonGenericTypeReferenceSyntax)element.AttributeConstructorTarget.MethodInvocation.TypeReference).AssemblyReference?.AssemblyName); |
| 142 | + Assert.Equal("System.Diagnostics.DebuggableAttribute", (((NonGenericTypeReferenceSyntax)element.AttributeConstructorTarget.MethodInvocation.TypeReference).ClassName)); |
| 143 | + Assert.True(element.AttributeConstructorTarget.MethodInvocation.Arguments.Arguments.First() is NonGenericTypeReferenceSyntax nonGeneric && |
| 144 | + nonGeneric.Prefix == TypePrefix.ValueType && |
| 145 | + nonGeneric.ClassName == "System.Diagnostics.DebuggableAttribute/DebuggingModes"); |
| 146 | + Assert.True( |
| 147 | + Enumerable.SequenceEqual( |
| 148 | + element.GetRawBytes(), |
| 149 | + new byte[] |
| 150 | + { |
| 151 | + 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 |
| 152 | + } |
| 153 | + ) |
| 154 | + ); |
| 155 | + } |
| 156 | + |
| 157 | + void TestElement4() |
| 158 | + { |
| 159 | + var element = (PermissionSetSyntax)result.DescendantNodes.ElementAt(3); |
| 160 | + Assert.Equal(SecurityAction.ReqMin, element.SecurityAction); |
| 161 | + Assert.True(element.GetRawBytes().SequenceEqual( |
| 162 | + s_complexCustomAttributePermissionSetDescendantByteData)); |
| 163 | + } |
| 164 | + |
| 165 | + void TestElement5() |
| 166 | + { |
| 167 | + var hash = (HashAlgorithmSyntax)result.DescendantNodes.ElementAt(4); |
| 168 | + Assert.Equal("0x00008004", hash.Value); |
| 169 | + } |
| 170 | + |
| 171 | + void TestElement6() |
| 172 | + { |
| 173 | + var inlineComment = (InlineCommentSyntax)result.DescendantNodes.ElementAt(5); |
| 174 | + Assert.Equal("SHA1", inlineComment.CommentText.Trim()); // remove leading and trailing whitespaces in comment text |
| 175 | + } |
| 176 | + |
| 177 | + void TestElement7() |
| 178 | + { |
| 179 | + var verDirective = (VerDirectiveSyntax)result.DescendantNodes.ElementAt(6); |
| 180 | + Assert.Equal('0', verDirective.Major); |
| 181 | + Assert.Equal('0', verDirective.Minor); |
| 182 | + Assert.Equal('0', verDirective.Build); |
| 183 | + Assert.Equal('0', verDirective.Revision); |
| 184 | + } |
| 185 | + } |
| 186 | +} |
0 commit comments