From b9250d7493e82ba38679a30021eebd46f74ac694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 7 Oct 2015 11:37:05 -0700 Subject: [PATCH] Add tests for static field layout Porting native NUTC tests for static field layout to the new type system. --- .../CoreTestAssembly/CoreTestAssembly.csproj | 1 + .../CoreTestAssembly/StaticFieldLayout.cs | 66 +++++ .../tests/StaticFieldLayoutTests.cs | 230 ++++++++++++++++++ src/TypeSystem/tests/TypeSystem.Tests.csproj | 1 + 4 files changed, 298 insertions(+) create mode 100644 src/TypeSystem/tests/CoreTestAssembly/StaticFieldLayout.cs create mode 100644 src/TypeSystem/tests/StaticFieldLayoutTests.cs diff --git a/src/TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj b/src/TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj index 2bda7169d8d..6ea6dc9a4b3 100644 --- a/src/TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj +++ b/src/TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj @@ -32,6 +32,7 @@ + diff --git a/src/TypeSystem/tests/CoreTestAssembly/StaticFieldLayout.cs b/src/TypeSystem/tests/CoreTestAssembly/StaticFieldLayout.cs new file mode 100644 index 00000000000..68bb885bb6c --- /dev/null +++ b/src/TypeSystem/tests/CoreTestAssembly/StaticFieldLayout.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; + +#pragma warning disable 169 + +namespace StaticFieldLayout +{ + struct NoPointers + { + static int int1; + static byte byte1; + static char char1; + } + + struct StillNoPointers + { + NoPointers noPointers1; + static bool bool1; + } + + class ClassNoPointers + { + static int int1; + static byte byte1; + static char char1; + } + + struct HasPointers + { + bool bool1; + static string string1; + static ClassNoPointers class1; + char char1; + } + + class MixPointersAndNonPointers + { + static string string1; + static int int1; + static ClassNoPointers class1; + static int int2; + static string string2; + } + + class EnsureInheritanceResetsStaticOffsets : MixPointersAndNonPointers + { + static int int3; + static string string3; + } + + class RvaTestClass + { + static void RvaTest() + { + int[] foo = new int[] { 0, 1, 2, 3, 4, 45, 5, 5 }; + } + + } + + struct StaticSelfRef + { + static StaticSelfRef selfRef1; + } +} diff --git a/src/TypeSystem/tests/StaticFieldLayoutTests.cs b/src/TypeSystem/tests/StaticFieldLayoutTests.cs new file mode 100644 index 00000000000..d203803c8b8 --- /dev/null +++ b/src/TypeSystem/tests/StaticFieldLayoutTests.cs @@ -0,0 +1,230 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; + +using Internal.TypeSystem.Ecma; +using Internal.TypeSystem; + +using Xunit; + +namespace TypeSystemTests +{ + public class StaticFieldLayoutTests + { + TestTypeSystemContext _context; + EcmaModule _testModule; + + public StaticFieldLayoutTests() + { + _context = new TestTypeSystemContext(TargetArchitecture.X64); + var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); + _context.SetSystemModule(systemModule); + + _testModule = systemModule; + } + + [Fact] + public void TestNoPointers() + { + MetadataType t = _testModule.GetType("StaticFieldLayout", "NoPointers"); + + foreach (var field in t.GetFields()) + { + if (!field.IsStatic) + continue; + + switch (field.Name) + { + case "int1": + Assert.Equal(0, field.Offset); + break; + case "byte1": + Assert.Equal(4, field.Offset); + break; + case "char1": + Assert.Equal(6, field.Offset); + break; + default: + throw new Exception(field.Name); + } + } + } + + [Fact] + public void TestStillNoPointers() + { + // + // Test that static offsets ignore instance fields preceeding them + // + + MetadataType t = _testModule.GetType("StaticFieldLayout", "StillNoPointers"); + + foreach (var field in t.GetFields()) + { + if (!field.IsStatic) + continue; + + switch (field.Name) + { + case "bool1": + Assert.Equal(0, field.Offset); + break; + default: + throw new Exception(field.Name); + } + } + } + + [Fact] + public void TestClassNoPointers() + { + // + // Ensure classes behave the same as structs when containing statics + // + + MetadataType t = _testModule.GetType("StaticFieldLayout", "ClassNoPointers"); + + foreach (var field in t.GetFields()) + { + if (!field.IsStatic) + continue; + + switch (field.Name) + { + case "int1": + Assert.Equal(0, field.Offset); + break; + case "byte1": + Assert.Equal(4, field.Offset); + break; + case "char1": + Assert.Equal(6, field.Offset); + break; + default: + throw new Exception(field.Name); + } + } + } + + [Fact] + public void TestHasPointers() + { + // + // Test a struct containing static types with pointers + // + + MetadataType t = _testModule.GetType("StaticFieldLayout", "HasPointers"); + + foreach (var field in t.GetFields()) + { + if (!field.IsStatic) + continue; + + switch (field.Name) + { + case "string1": + Assert.Equal(0, field.Offset); + break; + case "class1": + Assert.Equal(8, field.Offset); + break; + default: + throw new Exception(field.Name); + } + } + } + + [Fact] + public void TestMixPointersAndNonPointers() + { + // + // Test that static fields with GC pointers get separate offsets from non-GC fields + // + + MetadataType t = _testModule.GetType("StaticFieldLayout", "MixPointersAndNonPointers"); + + foreach (var field in t.GetFields()) + { + if (!field.IsStatic) + continue; + + switch (field.Name) + { + case "string1": + Assert.Equal(0, field.Offset); + break; + case "int1": + Assert.Equal(0, field.Offset); + break; + case "class1": + Assert.Equal(8, field.Offset); + break; + case "int2": + Assert.Equal(4, field.Offset); + break; + case "string2": + Assert.Equal(16, field.Offset); + break; + default: + throw new Exception(field.Name); + } + } + } + + [Fact] + public void TestEnsureInheritanceResetsStaticOffsets() + { + // + // Test that when inheriting a class with static fields, the derived slice's static fields + // are again offset from 0 + // + + MetadataType t = _testModule.GetType("StaticFieldLayout", "EnsureInheritanceResetsStaticOffsets"); + + foreach (var field in t.GetFields()) + { + if (!field.IsStatic) + continue; + + switch (field.Name) + { + case "int3": + Assert.Equal(0, field.Offset); + break; + case "string3": + Assert.Equal(0, field.Offset); + break; + default: + throw new Exception(field.Name); + } + } + } + + [Fact] + public void TestStaticSelfRef() + { + // + // Test that we can load a struct which has a static field referencing itself without + // going into an infinite loop + // + + MetadataType t = _testModule.GetType("StaticFieldLayout", "StaticSelfRef"); + + foreach (var field in t.GetFields()) + { + if (!field.IsStatic) + continue; + + switch (field.Name) + { + case "selfRef1": + Assert.Equal(0, field.Offset); + break; + default: + throw new Exception(field.Name); + } + } + } + } +} \ No newline at end of file diff --git a/src/TypeSystem/tests/TypeSystem.Tests.csproj b/src/TypeSystem/tests/TypeSystem.Tests.csproj index c4e06dc0eed..b01fd936660 100644 --- a/src/TypeSystem/tests/TypeSystem.Tests.csproj +++ b/src/TypeSystem/tests/TypeSystem.Tests.csproj @@ -35,6 +35,7 @@ +