From 0d3c0f77996495636cd2114cb6046138532e904d Mon Sep 17 00:00:00 2001 From: John Kleinschmidt Date: Wed, 13 Nov 2024 11:04:23 -0500 Subject: [PATCH] cleanup test debugging --- .../pipeline-segment-electron-test.yml | 2 +- script/screenCapture.bat | 275 ------------------ spec/index.js | 6 +- spec/lib/screen-helpers.ts | 2 +- spec/lib/spec-helpers.ts | 112 ------- spec/woa-screencap-spec.ts | 19 -- 6 files changed, 6 insertions(+), 410 deletions(-) delete mode 100644 script/screenCapture.bat delete mode 100644 spec/woa-screencap-spec.ts diff --git a/.github/workflows/pipeline-segment-electron-test.yml b/.github/workflows/pipeline-segment-electron-test.yml index 8e143691e8..aec772e9e9 100644 --- a/.github/workflows/pipeline-segment-electron-test.yml +++ b/.github/workflows/pipeline-segment-electron-test.yml @@ -244,7 +244,7 @@ jobs: echo ELECTRON_TEST_RESULTS_DIR=$PWD\junit >> $env:GITHUB_ENV # Get which tests are on this shard $tests_files=node script\split-tests ${{ matrix.shard }} 2 - echo tests_files="$tests_files spec\woa-screencap-spec.ts" >> $env:GITHUB_ENV + echo tests_files="$tests_files" >> $env:GITHUB_ENV if ('${{ inputs.target-arch }}' -eq 'x86') { echo npm_config_arch=ia32 >> $env:GITHUB_ENV } diff --git a/script/screenCapture.bat b/script/screenCapture.bat deleted file mode 100644 index d59beb7336..0000000000 --- a/script/screenCapture.bat +++ /dev/null @@ -1,275 +0,0 @@ -// 2>nul||@goto :batch -/* -:batch -@echo off -setlocal - -:: find csc.exe -set "csc=" -for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*csc.exe") do set "csc=%%#" - -if not exist "%csc%" ( - echo no .net framework installed - exit /b 10 -) - -if not exist "%~n0.exe" ( - call %csc% /nologo /r:"Microsoft.VisualBasic.dll" /out:"%~n0.exe" "%~dpsfnx0" || ( - exit /b %errorlevel% - ) -) -%~n0.exe %* -endlocal & exit /b %errorlevel% - -*/ - -// reference -// https://gallery.technet.microsoft.com/scriptcenter/eeff544a-f690-4f6b-a586-11eea6fc5eb8 - -using System; -using System.Runtime.InteropServices; -using System.Drawing; -using System.Drawing.Imaging; -using System.Collections.Generic; -using Microsoft.VisualBasic; - - -/// Provides functions to capture the entire screen, or a particular window, and save it to a file. - -public class ScreenCapture -{ - - /// Creates an Image object containing a screen shot the active window - - public Image CaptureActiveWindow() - { - return CaptureWindow(User32.GetForegroundWindow()); - } - - /// Creates an Image object containing a screen shot of the entire desktop - - public Image CaptureScreen() - { - return CaptureWindow(User32.GetDesktopWindow()); - } - - /// Creates an Image object containing a screen shot of a specific window - - private Image CaptureWindow(IntPtr handle) - { - // get te hDC of the target window - IntPtr hdcSrc = User32.GetWindowDC(handle); - // get the size - User32.RECT windowRect = new User32.RECT(); - User32.GetWindowRect(handle, ref windowRect); - int width = windowRect.right - windowRect.left; - int height = windowRect.bottom - windowRect.top; - // create a device context we can copy to - IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc); - // create a bitmap we can copy it to, - // using GetDeviceCaps to get the width/height - IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height); - // select the bitmap object - IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap); - // bitblt over - GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY); - // restore selection - GDI32.SelectObject(hdcDest, hOld); - // clean up - GDI32.DeleteDC(hdcDest); - User32.ReleaseDC(handle, hdcSrc); - // get a .NET image object for it - Image img = Image.FromHbitmap(hBitmap); - // free up the Bitmap object - GDI32.DeleteObject(hBitmap); - return img; - } - - public void CaptureActiveWindowToFile(string filename, ImageFormat format) - { - Image img = CaptureActiveWindow(); - img.Save(filename, format); - } - - public void CaptureScreenToFile(string filename, ImageFormat format) - { - Image img = CaptureScreen(); - img.Save(filename, format); - } - - static bool fullscreen = true; - static String file = "screenshot.bmp"; - static System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Bmp; - static String windowTitle = ""; - - static void parseArguments() - { - String[] arguments = Environment.GetCommandLineArgs(); - if (arguments.Length == 1) - { - printHelp(); - Environment.Exit(0); - } - if (arguments[1].ToLower().Equals("/h") || arguments[1].ToLower().Equals("/help")) - { - printHelp(); - Environment.Exit(0); - } - - file = arguments[1]; - Dictionary formats = - new Dictionary(); - - formats.Add("bmp", System.Drawing.Imaging.ImageFormat.Bmp); - formats.Add("emf", System.Drawing.Imaging.ImageFormat.Emf); - formats.Add("exif", System.Drawing.Imaging.ImageFormat.Exif); - formats.Add("jpg", System.Drawing.Imaging.ImageFormat.Jpeg); - formats.Add("jpeg", System.Drawing.Imaging.ImageFormat.Jpeg); - formats.Add("gif", System.Drawing.Imaging.ImageFormat.Gif); - formats.Add("png", System.Drawing.Imaging.ImageFormat.Png); - formats.Add("tiff", System.Drawing.Imaging.ImageFormat.Tiff); - formats.Add("wmf", System.Drawing.Imaging.ImageFormat.Wmf); - - - String ext = ""; - if (file.LastIndexOf('.') > -1) - { - ext = file.ToLower().Substring(file.LastIndexOf('.') + 1, file.Length - file.LastIndexOf('.') - 1); - } - else - { - Console.WriteLine("Invalid file name - no extension"); - Environment.Exit(7); - } - - try - { - format = formats[ext]; - } - catch (Exception e) - { - Console.WriteLine("Probably wrong file format:" + ext); - Console.WriteLine(e.ToString()); - Environment.Exit(8); - } - - - if (arguments.Length > 2) - { - windowTitle = arguments[2]; - fullscreen = false; - } - - } - - static void printHelp() - { - //clears the extension from the script name - String scriptName = Environment.GetCommandLineArgs()[0]; - scriptName = scriptName.Substring(0, scriptName.Length); - Console.WriteLine(scriptName + " captures the screen or the active window and saves it to a file."); - Console.WriteLine(""); - Console.WriteLine("Usage:"); - Console.WriteLine(" " + scriptName + " filename [WindowTitle]"); - Console.WriteLine(""); - Console.WriteLine("filename - the file where the screen capture will be saved"); - Console.WriteLine(" allowed file extensions are - Bmp,Emf,Exif,Gif,Icon,Jpeg,Png,Tiff,Wmf."); - Console.WriteLine("WindowTitle - instead of capture whole screen you can point to a window "); - Console.WriteLine(" with a title which will put on focus and captuted."); - Console.WriteLine(" For WindowTitle you can pass only the first few characters."); - Console.WriteLine(" If don't want to change the current active window pass only \"\""); - } - - public static void Main() - { - User32.SetProcessDPIAware(); - - parseArguments(); - ScreenCapture sc = new ScreenCapture(); - if (!fullscreen && !windowTitle.Equals("")) - { - try - { - - Interaction.AppActivate(windowTitle); - Console.WriteLine("setting " + windowTitle + " on focus"); - } - catch (Exception e) - { - Console.WriteLine("Probably there's no window like " + windowTitle); - Console.WriteLine(e.ToString()); - Environment.Exit(9); - } - - - } - try - { - if (fullscreen) - { - Console.WriteLine("Taking a capture of the whole screen to " + file); - sc.CaptureScreenToFile(file, format); - } - else - { - Console.WriteLine("Taking a capture of the active window to " + file); - sc.CaptureActiveWindowToFile(file, format); - } - } - catch (Exception e) - { - Console.WriteLine("Check if file path is valid " + file); - Console.WriteLine(e.ToString()); - } - } - - /// Helper class containing Gdi32 API functions - - private class GDI32 - { - - public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter - [DllImport("gdi32.dll")] - public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, - int nWidth, int nHeight, IntPtr hObjectSource, - int nXSrc, int nYSrc, int dwRop); - [DllImport("gdi32.dll")] - public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, - int nHeight); - [DllImport("gdi32.dll")] - public static extern IntPtr CreateCompatibleDC(IntPtr hDC); - [DllImport("gdi32.dll")] - public static extern bool DeleteDC(IntPtr hDC); - [DllImport("gdi32.dll")] - public static extern bool DeleteObject(IntPtr hObject); - [DllImport("gdi32.dll")] - public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject); - } - - - /// Helper class containing User32 API functions - - private class User32 - { - [StructLayout(LayoutKind.Sequential)] - public struct RECT - { - public int left; - public int top; - public int right; - public int bottom; - } - [DllImport("user32.dll")] - public static extern IntPtr GetDesktopWindow(); - [DllImport("user32.dll")] - public static extern IntPtr GetWindowDC(IntPtr hWnd); - [DllImport("user32.dll")] - public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC); - [DllImport("user32.dll")] - public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect); - [DllImport("user32.dll")] - public static extern IntPtr GetForegroundWindow(); - [DllImport("user32.dll")] - public static extern int SetProcessDPIAware(); - } -} diff --git a/spec/index.js b/spec/index.js index d58677d58c..095f00e4e9 100644 --- a/spec/index.js +++ b/spec/index.js @@ -170,8 +170,10 @@ app.whenReady().then(async () => { } const cb = () => { - console.log(`In SPEC CB, process next tick with failures: ${runner.failures} for ${process.platform}`); - process.exit(runner.failures); + // Ensure the callback is called after runner is defined + process.nextTick(() => { + process.exit(runner.failures); + }); }; // Set up chai in the correct order diff --git a/spec/lib/screen-helpers.ts b/spec/lib/screen-helpers.ts index a63e92ab5a..0fb3128611 100644 --- a/spec/lib/screen-helpers.ts +++ b/spec/lib/screen-helpers.ts @@ -122,7 +122,7 @@ export class ScreenCapture { return this._expectImpl(findPoint(this.display.size), hexColor, true); } - public async captureFrame (): Promise { + private async captureFrame (): Promise { const sources = await desktopCapturer.getSources({ types: ['screen'], thumbnailSize: this.display.size diff --git a/spec/lib/spec-helpers.ts b/spec/lib/spec-helpers.ts index dca767a718..85a31ddd3b 100644 --- a/spec/lib/spec-helpers.ts +++ b/spec/lib/spec-helpers.ts @@ -3,128 +3,16 @@ import { BrowserWindow } from 'electron/main'; import { AssertionError } from 'chai'; import { SuiteFunction, TestFunction } from 'mocha'; -import { createHook } from 'node:async_hooks'; import * as childProcess from 'node:child_process'; -import { readFileSync } from 'node:fs'; import * as http from 'node:http'; import * as http2 from 'node:http2'; import * as https from 'node:https'; import * as net from 'node:net'; import * as path from 'node:path'; -import { relative } from 'node:path'; import { setTimeout } from 'node:timers/promises'; import * as url from 'node:url'; -import { fileURLToPath } from 'node:url'; import * as v8 from 'node:v8'; -const IGNORED_TYPES = [ - 'TIMERWRAP', - 'PROMISE', - 'PerformanceObserver', - 'RANDOMBYTESREQUEST' -]; - -let asyncResources:Map; -let hook:any; - -export function initWhyIsNodeRunning () { - asyncResources = new Map(); - hook = createHook({ - init (asyncId, type, triggerAsyncId, resource) { - if (IGNORED_TYPES.includes(type)) { - return; - } - - const stacks = captureStackTraces().slice(1); - - asyncResources.set(asyncId, { - type, - resource, - stacks - }); - }, - destroy (asyncId) { - asyncResources.delete(asyncId); - } - }); - - hook.enable(); -} - -export function whyIsNodeRunning () { - hook.disable(); - - const activeAsyncResources = Array.from(asyncResources.values()) - .filter(({ resource }) => resource.hasRef?.() ?? true); - - console.error(`There are ${activeAsyncResources.length} handle(s) keeping the process running.`); - - for (const asyncResource of activeAsyncResources) { - printStacks(asyncResource, console); - } -} - -function printStacks (asyncResource:any, logger:any) { - const stacks = asyncResource.stacks.filter((stack:any) => { - const fileName = stack.getFileName(); - return fileName !== null && !fileName.startsWith('node:internal/async_hooks'); - }); - - logger.error(''); - logger.error(`# ${asyncResource.type}`); - - if (!stacks[0]) { - logger.error('(unknown stack trace)'); - return; - } - - const maxLength = stacks.reduce((length:any, stack:any) => Math.max(length, formatLocation(stack).length), 0); - - for (const stack of stacks) { - const location = formatLocation(stack); - const padding = ' '.repeat(maxLength - location.length); - - try { - const lines = readFileSync(normalizeFilePath(stack.getFileName()), 'utf-8').split(/\n|\r\n/); - const line = lines[stack.getLineNumber() - 1].trim(); - - logger.error(`${location}${padding} - ${line}`); - } catch { - logger.error(`${location}${padding}`); - } - } -} - -function formatLocation (stack:any) { - const filePath = formatFilePath(stack.getFileName()); - return `${filePath}:${stack.getLineNumber()}`; -} - -function formatFilePath (filePath:any) { - const absolutePath = normalizeFilePath(filePath); - const relativePath = relative(process.cwd(), absolutePath); - - return relativePath.startsWith('..') ? absolutePath : relativePath; -} - -function normalizeFilePath (filePath:any) { - return filePath.startsWith('file://') ? fileURLToPath(filePath) : filePath; -} - -// See: https://v8.dev/docs/stack-trace-api -function captureStackTraces () { - const target:any = {}; - const original = Error.prepareStackTrace; - - Error.prepareStackTrace = (error, stackTraces) => stackTraces; // eslint-disable-line - Error.captureStackTrace(target, captureStackTraces); - - const capturedTraces = target.stack; - Error.prepareStackTrace = original; - - return capturedTraces; -} - const addOnly = (fn: Function): T => { const wrapped = (...args: any[]) => { return fn(...args); diff --git a/spec/woa-screencap-spec.ts b/spec/woa-screencap-spec.ts deleted file mode 100644 index 7f8f4dcba5..0000000000 --- a/spec/woa-screencap-spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { screen } from 'electron/main'; - -import { createArtifactWithRandomId } from './lib/artifacts'; -import { ScreenCapture } from './lib/screen-helpers'; -import { ifit } from './lib/spec-helpers'; - -describe('trying to get screen capture on WOA', () => { - ifit(process.platform === 'win32' && process.arch === 'arm64')('does it work', async () => { - const display = screen.getPrimaryDisplay(); - const screenCapture = new ScreenCapture(display); - const frame = await screenCapture.captureFrame(); - // Save the image as an artifact for better debugging - const artifactName = await createArtifactWithRandomId( - (id) => `screen-cap-${id}.png`, - frame.toPNG() - ); - console.log(`Created artifact at: ${artifactName}`); - }); -});