|
17 | 17 | using Nuke.Common.Utilities;
|
18 | 18 | using System.Collections;
|
19 | 19 | using System.Threading.Tasks;
|
| 20 | +using DiffMatchPatch; |
20 | 21 | using Logger = Serilog.Log;
|
21 | 22 |
|
22 | 23 | partial class Build
|
@@ -137,6 +138,84 @@ partial class Build
|
137 | 138 | arguments: $"--build {NativeBuildDirectory} --parallel {Environment.ProcessorCount} --target wrapper");
|
138 | 139 | });
|
139 | 140 |
|
| 141 | + Target TestNativeWrapper => _ => _ |
| 142 | + .Unlisted() |
| 143 | + .Description("Test that the Native wrapper symbols haven't changed") |
| 144 | + .After(CompileNativeWrapper) |
| 145 | + .OnlyWhenStatic(() => IsLinux) |
| 146 | + .Executes(() => |
| 147 | + { |
| 148 | + var (arch, _) = GetUnixArchitectureAndExtension(); |
| 149 | + var libraryPath = ProfilerDeployDirectory / arch / LinuxApiWrapperLibrary; |
| 150 | + |
| 151 | + var output = Nm.Value($"-D {libraryPath}").Select(x => x.Text).ToList(); |
| 152 | + |
| 153 | + // Gives output similar to this: |
| 154 | + // 0000000000006bc8 D DdDotnetFolder |
| 155 | + // 0000000000006bd0 D DdDotnetMuslFolder |
| 156 | + // w _ITM_deregisterTMCloneTable |
| 157 | + // w _ITM_registerTMCloneTable |
| 158 | + // w __cxa_finalize |
| 159 | + // w __deregister_frame_info |
| 160 | + // U __errno_location |
| 161 | + // U __tls_get_addr |
| 162 | + // 0000000000002d1b T _fini |
| 163 | + // 0000000000002d18 T _init |
| 164 | + // 0000000000003d70 T accept |
| 165 | + // 0000000000003e30 T accept4 |
| 166 | + // U access |
| 167 | + // |
| 168 | + // The types of symbols are: |
| 169 | + // D: Data section symbol. These symbols are initialized global variables. |
| 170 | + // w: Weak symbol. These symbols are weakly referenced and can be overridden by other symbols. |
| 171 | + // U: Undefined symbol. These symbols are referenced in the file but defined elsewhere. |
| 172 | + // T: Text section symbol. These symbols are functions or executable code. |
| 173 | + // B: BSS (Block Started by Symbol) section symbol. These symbols are uninitialized global variables. |
| 174 | + // |
| 175 | + // We only care about the Undefined symbols - we don't want to accidentally add more of them |
| 176 | + |
| 177 | + Logger.Debug("NM output: {Output}", string.Join(Environment.NewLine, output)); |
| 178 | + |
| 179 | + var symbols = output |
| 180 | + .Select(x => x.Trim()) |
| 181 | + .Where(x => x.StartsWith("U ")) |
| 182 | + .Select(x => x.TrimStart("U ")) |
| 183 | + .OrderBy(x => x) |
| 184 | + .ToList(); |
| 185 | + |
| 186 | + |
| 187 | + var received = string.Join(Environment.NewLine, symbols); |
| 188 | + var verifiedPath = TestsDirectory / "snapshots" / $"native-wrapper-symbols-{UnixArchitectureIdentifier}.verified.txt"; |
| 189 | + var verified = File.Exists(verifiedPath) |
| 190 | + ? File.ReadAllText(verifiedPath) |
| 191 | + : string.Empty; |
| 192 | + |
| 193 | + Logger.Information("Comparing snapshot of Undefined symbols in the Native Wrapper library using {Path}...", verifiedPath); |
| 194 | + |
| 195 | + var dmp = new diff_match_patch(); |
| 196 | + var diff = dmp.diff_main(verified, received); |
| 197 | + dmp.diff_cleanupSemantic(diff); |
| 198 | + |
| 199 | + var changedSymbols = diff |
| 200 | + .Where(x => x.operation != Operation.EQUAL) |
| 201 | + .Select(x => x.text.Trim()) |
| 202 | + .ToList(); |
| 203 | + |
| 204 | + if (changedSymbols.Count == 0) |
| 205 | + { |
| 206 | + Logger.Information("No changes found in Undefined symbols in the Native Wrapper library"); |
| 207 | + return; |
| 208 | + } |
| 209 | + |
| 210 | + PrintDiff(diff); |
| 211 | + |
| 212 | + throw new Exception($"Found differences in undefined symbols ({string.Join(",", changedSymbols)}) in the Native Wrapper library. " + |
| 213 | + "Verify that these changes are expected, and will not cause problems. " + |
| 214 | + "Removing symbols is generally a safe operation, but adding them could cause crashes. " + |
| 215 | + $"If the new symbols are safe to add, update the snapshot file at {verifiedPath} with the " + |
| 216 | + "new values"); |
| 217 | + }); |
| 218 | + |
140 | 219 | Target CompileNativeWrapperNativeTests => _ => _
|
141 | 220 | .Unlisted()
|
142 | 221 | .Description("Compile Native wrapper unit tests")
|
|
0 commit comments