Ikramuzzaman Sifat
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Toloka 1: https://hackmd.io/@P_oDzqNMQBqjwVAD_Ao-Dw/Bkx0DQwKC Toloka 3: https://hackmd.io/@P_oDzqNMQBqjwVAD_Ao-Dw/Sy1bIKbqR Is there any kind of ambiguity or lack of context? or any part of the instruction already complete? what was previous in the code ? and what minimal changes required to meet the instruction? give solution in short then. with mentioning code change. if needed re-evaluate the instruction. https://notlabel-studio.toloka-test.ai/projects/1355 https://notlabel-studio.toloka-test.ai/projects/1355/data?tab=15792&page=183 ### Batch re-write or in progress issue 662517 - updated to completed (changed by p-coding robot batch-rewrite issue) 63010, 660277 - Seems those were already completed, don't know why these are marked as IN PROGRESS 666281 - Updated to Completed (this was previously claimed by sazin) 669637 - completed now. (claimed by unknown) 662199, 662050, 662472, 661988 - already completed and no issue (changed by p-coding robot batch-rewrite issue) ### Both 712490 712243 712241 711953 712034 ### File: ```typescript= import * as assert from 'assert'; import * as cp from 'child_process'; import * as fs from 'fs'; import getPort = require('get-port'); import * as http from 'http'; import { tmpdir } from 'os'; import * as path from 'path'; import * as sinon from 'sinon'; import util = require('util'); import { DebugConfiguration } from 'vscode'; import { DebugClient } from 'vscode-debugadapter-testsupport'; import { ILocation } from 'vscode-debugadapter-testsupport/lib/debugClient'; import { DebugProtocol } from 'vscode-debugprotocol'; import { Delve, escapeGoModPath, GoDebugSession, PackageBuildInfo, RemoteSourcesAndPackages, } from '../../src/debugAdapter/goDebug'; import { GoDebugConfigurationProvider } from '../../src/goDebugConfiguration'; import { getBinPath, getGoVersion, rmdirRecursive } from '../../src/util'; import { killProcessTree } from '../../src/utils/processUtils'; suite('Path Manipulation Tests', () => { test('escapeGoModPath works', () => { assert.strictEqual(escapeGoModPath('BurnSushi/test.go'), '!burn!sushi/test.go'); }); }); suite('GoDebugSession Tests', async () => { const workspaceFolder = '/usr/workspacefolder'; const delve: Delve = {} as Delve; let goDebugSession: GoDebugSession; let remoteSourcesAndPackages: RemoteSourcesAndPackages; let fileSystem: typeof fs; let previousEnv: any; setup(() => { previousEnv = Object.assign({}, process.env); process.env.GOPATH = '/usr/gopath'; process.env.GOROOT = '/usr/goroot'; remoteSourcesAndPackages = new RemoteSourcesAndPackages(); fileSystem = { existsSync: () => false } as unknown as typeof fs; delve.program = workspaceFolder; delve.isApiV1 = false; goDebugSession = new GoDebugSession(true, false, fileSystem); goDebugSession['delve'] = delve; goDebugSession['remoteSourcesAndPackages'] = remoteSourcesAndPackages; }); teardown(() => { process.env = previousEnv; sinon.restore(); }); test('inferRemotePathFromLocalPath works', () => { const sourceFileMapping = new Map<string, string[]>(); sourceFileMapping.set('main.go', ['/app/hello-world/main.go', '/app/main.go']); sourceFileMapping.set('blah.go', ['/app/blah.go']); remoteSourcesAndPackages.remoteSourceFilesNameGrouping = sourceFileMapping; const inferredPath = goDebugSession['inferRemotePathFromLocalPath']( 'C:\\Users\\Documents\\src\\hello-world\\main.go'); assert.strictEqual(inferredPath, '/app/hello-world/main.go'); }); test('inferLocalPathFromRemoteGoPackage works for package in workspaceFolder', () => { const remotePath = '/src/hello-world/morestrings/morestrings.go'; const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world/morestrings', DirectoryPath: '/src/hello-world/morestrings', Files: ['/src/hello-world/morestrings/lessstrings.go', '/src/hello-world/morestrings/morestrings.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'FooBar/test', DirectoryPath: 'remote/pkg/mod/!foo!bar/test@v1.0.2', Files: ['remote/pkg/mod/!foo!bar/test@v1.0.2/test.go'] }; const localPath = path.join(workspaceFolder, 'hello-world/morestrings/morestrings.go'); const existsSyncStub = sinon.stub(fileSystem, 'existsSync'); existsSyncStub.withArgs(localPath).returns(true); remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage]; goDebugSession['localPathSeparator'] = '/'; const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath); assert.strictEqual(inferredLocalPath, localPath); }); test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/pkg/mod', () => { const remotePath = 'remote/pkg/mod/!foo!bar/test@v1.0.2/test.go'; const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world', DirectoryPath: '/src/hello-world', Files: ['src/hello-world/hello.go', 'src/hello-world/world.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'FooBar/test', DirectoryPath: 'remote/pkg/mod/!foo!bar/test@v1.0.2', Files: ['remote/pkg/mod/!foo!bar/test@v1.0.2/test.go'] }; const localPath = path.join(process.env.GOPATH, 'pkg/mod/!foo!bar/test@v1.0.2/test.go'); const existsSyncStub = sinon.stub(fileSystem, 'existsSync'); existsSyncStub.withArgs(localPath).returns(true); remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage]; goDebugSession['localPathSeparator'] = '/'; const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath); assert.strictEqual(inferredLocalPath, localPath); }); test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/pkg/mod with relative path', () => { const remotePath = '!foo!bar/test@v1.0.2/test.go'; const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world', DirectoryPath: '/src/hello-world', Files: ['src/hello-world/hello.go', 'src/hello-world/world.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'FooBar/test', DirectoryPath: '!foo!bar/test@v1.0.2', Files: ['!foo!bar/test@v1.0.2/test.go'] }; const localPath = path.join(process.env.GOPATH, 'pkg/mod/!foo!bar/test@v1.0.2/test.go'); const existsSyncStub = sinon.stub(fileSystem, 'existsSync'); existsSyncStub.withArgs(localPath).returns(true); remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage]; goDebugSession['localPathSeparator'] = '/'; const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath); assert.strictEqual(inferredLocalPath, localPath); }); test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/src', () => { const remotePath = 'remote/gopath/src/foobar/test@v1.0.2-abcde-34/test.go'; const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world', DirectoryPath: '/src/hello-world', Files: ['src/hello-world/hello.go', 'src/hello-world/world.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'foobar/test', DirectoryPath: 'remote/gopath/src/foobar/test@v1.0.2-abcde-34', Files: ['remote/gopath/src/foobar/test@v1.0.2-abcde-34/test.go'] }; const localPath = path.join(process.env.GOPATH, 'src', 'foobar/test@v1.0.2-abcde-34/test.go'); const existsSyncStub = sinon.stub(fileSystem, 'existsSync'); existsSyncStub.withArgs(localPath).returns(true); remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage]; goDebugSession['localPathSeparator'] = '/'; const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath); assert.strictEqual(inferredLocalPath, localPath); }); test('inferLocalPathFromRemoteGoPackage works for package in GOPATH/src with relative path', () => { const remotePath = 'foobar/test@v1.0.2/test.go'; const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world', DirectoryPath: '/src/hello-world', Files: ['src/hello-world/hello.go', 'src/hello-world/world.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'foobar/test', DirectoryPath: 'foobar/test@v1.0.2', Files: ['foobar/test@v1.0.2/test.go'] }; const localPath = path.join(process.env.GOPATH, 'src', 'foobar/test@v1.0.2/test.go'); const existsSyncStub = sinon.stub(fileSystem, 'existsSync'); existsSyncStub.withArgs(localPath).returns(true); remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage]; goDebugSession['localPathSeparator'] = '/'; const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath); assert.strictEqual(inferredLocalPath, localPath); }); test('inferLocalPathFromRemoteGoPackage works for package in GOROOT/src', () => { const remotePath = 'remote/goroot/src/foobar/test@v1.0.2/test.go'; const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world', DirectoryPath: '/src/hello-world', Files: ['src/hello-world/hello.go', 'src/hello-world/world.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'foobar/test', DirectoryPath: 'remote/goroot/src/foobar/test@v1.0.2', Files: ['remote/goroot/src/foobar/test@v1.0.2/test.go'] }; const localPath = path.join(process.env.GOROOT, 'src', 'foobar/test@v1.0.2/test.go'); const existsSyncStub = sinon.stub(fileSystem, 'existsSync'); existsSyncStub.withArgs(localPath).returns(true); remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage]; goDebugSession['localPathSeparator'] = '/'; const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath); assert.strictEqual(inferredLocalPath, localPath); }); test('inferLocalPathFromRemoteGoPackage works for package in GOROOT/src with relative path', () => { const remotePath = 'foobar/test@v1.0.2/test.go'; const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world', DirectoryPath: '/src/hello-world', Files: ['src/hello-world/hello.go', 'src/hello-world/world.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'foobar/test', DirectoryPath: 'foobar/test@v1.0.2', Files: ['foobar/test@v1.0.2/test.go'] }; const localPath = path.join(process.env.GOROOT, 'src', 'foobar/test@v1.0.2/test.go'); const existsSyncStub = sinon.stub(fileSystem, 'existsSync'); existsSyncStub.withArgs(localPath).returns(true); remoteSourcesAndPackages.remotePackagesBuildInfo = [helloPackage, testPackage]; goDebugSession['localPathSeparator'] = '/'; const inferredLocalPath = goDebugSession['inferLocalPathFromRemoteGoPackage'](remotePath); assert.strictEqual(inferredLocalPath, localPath); }); }); suite('RemoteSourcesAndPackages Tests', () => { const helloPackage: PackageBuildInfo = { ImportPath: 'hello-world', DirectoryPath: '/src/hello-world', Files: ['src/hello-world/hello.go', 'src/hello-world/world.go'] }; const testPackage: PackageBuildInfo = { ImportPath: 'test', DirectoryPath: '/src/test', Files: ['src/test/test.go'] }; const sources = ['src/hello-world/hello.go', 'src/hello-world/world.go', 'src/test/test.go']; let remoteSourcesAndPackages: RemoteSourcesAndPackages; let delve: Delve; setup(() => { delve = { callPromise: () => ({}), isApiV1: false } as unknown as Delve; remoteSourcesAndPackages = new RemoteSourcesAndPackages(); }); teardown(() => { sinon.restore(); }); test('initializeRemotePackagesAndSources retrieves remote packages and sources', async () => { const stub = sinon.stub(delve, 'callPromise'); stub.withArgs('ListPackagesBuildInfo', [{ IncludeFiles: true }]) .returns(Promise.resolve({ List: [helloPackage, testPackage] })); stub.withArgs('ListSources', [{}]) .returns(Promise.resolve({ Sources: sources })); await remoteSourcesAndPackages.initializeRemotePackagesAndSources(delve); assert.deepEqual(remoteSourcesAndPackages.remoteSourceFiles, sources); assert.deepEqual(remoteSourcesAndPackages.remotePackagesBuildInfo, [helloPackage, testPackage]); }); }); // Test suite adapted from: // https://github.com/microsoft/vscode-mock-debug/blob/master/src/tests/adapter.test.ts suite('Go Debug Adapter', function () { this.timeout(60_000); const debugConfigProvider = new GoDebugConfigurationProvider(); const DEBUG_ADAPTER = path.join('.', 'out', 'src', 'debugAdapter', 'goDebug.js'); const PROJECT_ROOT = path.normalize(path.join(__dirname, '..', '..', '..')); const DATA_ROOT = path.join(PROJECT_ROOT, 'test', 'testdata'); const remoteAttachConfig = { name: 'Attach', type: 'go', request: 'attach', mode: 'remote', host: '127.0.0.1', port: 3456, }; let dc: DebugClient; setup(() => { dc = new DebugClient('node', path.join(PROJECT_ROOT, DEBUG_ADAPTER), 'go'); // Launching delve may take longer than the default timeout of 5000. dc.defaultTimeout = 20_000; // To connect to a running debug server for debugging the tests, specify PORT. return dc.start(); }); teardown(() => dc.stop()); /** * This function sets up a server that returns helloworld on serverPort. * The server will be started as a Delve remote headless instance * that will listen on the specified dlvPort. * We are using a server as opposed to a long-running program * because we can use responses to better test when the program is * running vs stopped/killed. */ async function setUpRemoteProgram( dlvPort: number, serverPort: number, acceptMultiClient = true, continueOnStart = true): Promise<cp.ChildProcess> { const serverFolder = path.join(DATA_ROOT, 'helloWorldServer'); const toolPath = getBinPath('dlv'); const args = ['debug', '--api-version=2', '--headless', `--listen=127.0.0.1:${dlvPort}`]; if (acceptMultiClient) { args.push('--accept-multiclient'); } if (continueOnStart) { args.push('--continue'); } const childProcess = cp.spawn(toolPath, args, {cwd: serverFolder, env: { PORT: `${serverPort}`, ...process.env}}); // Give dlv a few seconds to start. await new Promise((resolve) => setTimeout(resolve, 10_000)); return childProcess; } /** * Helper function to set up remote attach configuration. * This will issue an initializeRequest, followed by attachRequest. * It will then wait for an initializedEvent before sending a breakpointRequest * if breakpoints are provided. Lastly the configurationDoneRequest will be sent. * NOTE: For simplicity, this function assumes the breakpoints are in the same file. */ async function setUpRemoteAttach(config: DebugConfiguration, breakpoints: ILocation[] = []): Promise<void> { const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); console.log(`Sending initializing request for remote attach setup.`); const initializedResult = await dc.initializeRequest(); assert.ok(initializedResult.success); // When the attach request is completed successfully, we should get // an initialized event. await Promise.all([ new Promise(async (resolve) => { console.log(`Setting up attach request for ${JSON.stringify(debugConfig)}.`); const attachResult = await dc.attachRequest(debugConfig as DebugProtocol.AttachRequestArguments); assert.ok(attachResult.success); resolve(); }), dc.waitForEvent('initialized') ]); if (breakpoints.length) { console.log(`Sending set breakpoints request for remote attach setup.`); const breakpointsResult = await dc.setBreakpointsRequest({source: {path: breakpoints[0].path}, breakpoints}); assert.ok(breakpointsResult.success && breakpointsResult.body.breakpoints.length === breakpoints.length); // Verify that there are no non-verified breakpoints. breakpointsResult.body.breakpoints.forEach((breakpoint) => { assert.ok(breakpoint.verified); }); } console.log(`Sending configuration done request for remote attach setup.`); const configurationDoneResult = await dc.configurationDoneRequest(); assert.ok(configurationDoneResult.success); } /** * Helper function to retrieve a stopped event for a breakpoint. * This function will keep calling action() until we receive a stoppedEvent. * Will return undefined if the result of repeatedly calling action does not * induce a stoppedEvent. */ async function waitForBreakpoint(action: () => void, breakpoint: ILocation): Promise<void> { const assertStoppedLocation = dc.assertStoppedLocation('breakpoint', breakpoint); await new Promise((res) => setTimeout(res, 1_000)); action(); await assertStoppedLocation; } /** * Helper function to assert that a variable has a particular value. * This should be called when the program is stopped. * * The following requests are issued by this function to determine the * value of the variable: * 1. threadsRequest * 2. stackTraceRequest * 3. scopesRequest * 4. variablesRequest */ async function assertVariableValue(name: string, val: string): Promise<void> { const threadsResponse = await dc.threadsRequest(); assert(threadsResponse.success); const stackTraceResponse = await dc.stackTraceRequest({ threadId: threadsResponse.body.threads[0].id }); assert(stackTraceResponse.success); const scopesResponse = await dc.scopesRequest({ frameId: stackTraceResponse.body.stackFrames[0].id }); assert(scopesResponse.success); const variablesResponse = await dc.variablesRequest({ variablesReference: scopesResponse.body.scopes[0].variablesReference }); assert(variablesResponse.success); // Locate the variable with the matching name. const i = variablesResponse.body.variables.findIndex((v) => v.name === name); assert(i >= 0); // Check that the value of name is val. assert.strictEqual(variablesResponse.body.variables[i].value, val); } suite('basic', () => { test('unknown request should produce error', (done) => { dc.send('illegal_request').then(() => { done(new Error('does not report error on unknown request')); }).catch(() => { done(); }); }); }); suite('initialize', () => { test('should return supported features', () => { return dc.initializeRequest().then((response) => { response.body = response.body || {}; assert.strictEqual(response.body.supportsConditionalBreakpoints, true); assert.strictEqual(response.body.supportsConfigurationDoneRequest, true); assert.strictEqual(response.body.supportsSetVariable, true); }); }); test('should produce error for invalid \'pathFormat\'', (done) => { dc.initializeRequest({ adapterID: 'mock', linesStartAt1: true, columnsStartAt1: true, pathFormat: 'url' }).then((response) => { done(new Error('does not report error on invalid \'pathFormat\' attribute')); }).catch((err) => { // error expected done(); }); }); }); suite('launch', () => { test('should run program to the end', () => { const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated') ]); }); test('should stop on entry', () => { const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, stopOnEntry: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.configurationSequence(), dc.launch(debugConfig), // The debug adapter does not support a stack trace request // when there are no goroutines running. Which is true when it is stopped // on entry. Therefore we would need another method from dc.assertStoppedLocation // to check the debugger is stopped on entry. dc.waitForEvent('stopped').then((event) => { const stevent = event as DebugProtocol.StoppedEvent; assert.strictEqual(stevent.body.reason, 'entry'); }) ]); }); test('should debug a file', () => { const PROGRAM = path.join(DATA_ROOT, 'baseTest', 'test.go'); const config = { name: 'Launch file', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated') ]); }); test('should debug a single test', () => { const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const config = { name: 'Launch file', type: 'go', request: 'launch', mode: 'test', program: PROGRAM, args: [ '-test.run', 'TestMe' ] }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated') ]); }); test('should debug a test package', () => { const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const config = { name: 'Launch file', type: 'go', request: 'launch', mode: 'test', program: PROGRAM }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.configurationSequence(), dc.launch(debugConfig), dc.waitForEvent('terminated') ]); }); }); suite('set current working directory', () => { test('should debug program with cwd set', async () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest'); const FILE = path.join(PROGRAM, 'main.go'); const BREAKPOINT_LINE = 11; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, cwd: WD, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); await assertVariableValue('strdat', '"Hello, World!"'); }); test('should debug program without cwd set', async () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest'); const FILE = path.join(PROGRAM, 'main.go'); const BREAKPOINT_LINE = 11; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); await assertVariableValue('strdat', '"Goodbye, World."'); }); test('should debug file program with cwd set', async () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest', 'main.go'); const FILE = PROGRAM; const BREAKPOINT_LINE = 11; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, cwd: WD, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); await assertVariableValue('strdat', '"Hello, World!"'); }); test('should debug file program without cwd set', async () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest', 'main.go'); const FILE = PROGRAM; const BREAKPOINT_LINE = 11; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); await assertVariableValue('strdat', '"Goodbye, World."'); }); test('should run program with cwd set (noDebug)', () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, cwd: WD, noDebug: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.launch(debugConfig), dc.waitForEvent('output').then((event) => { assert.strictEqual(event.body.output, 'Hello, World!\n'); }) ]); }); test('should run program without cwd set (noDebug)', () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, noDebug: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.launch(debugConfig), dc.waitForEvent('output').then((event) => { assert.strictEqual(event.body.output, 'Goodbye, World.\n'); }) ]); }); test('should run file program with cwd set (noDebug)', () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest', 'main.go'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, cwd: WD, noDebug: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.launch(debugConfig), dc.waitForEvent('output').then((event) => { assert.strictEqual(event.body.output, 'Hello, World!\n'); }) ]); }); test('should run file program without cwd set (noDebug)', () => { const WD = path.join(DATA_ROOT, 'cwdTest'); const PROGRAM = path.join(WD, 'cwdTest', 'main.go'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, noDebug: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.launch(debugConfig), dc.waitForEvent('output').then((event) => { assert.strictEqual(event.body.output, 'Goodbye, World.\n'); }) ]); }); }); suite('remote attach', () => { let childProcess: cp.ChildProcess; let server: number; let debugConfig: DebugConfiguration; setup(async () => { server = await getPort(); remoteAttachConfig.port = await getPort(); debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, remoteAttachConfig); }); teardown(async () => { await dc.disconnectRequest({restart: false}); await killProcessTree(childProcess); // Wait 2 seconds for the process to be killed. await new Promise((resolve) => setTimeout(resolve, 2_000)); }); test('can connect and initialize using external dlv --headless --accept-multiclient=true --continue=true', async () => { childProcess = await setUpRemoteProgram(remoteAttachConfig.port, server, true, true); await setUpRemoteAttach(debugConfig); }); test('can connect and initialize using external dlv --headless --accept-multiclient=false --continue=false', async () => { childProcess = await setUpRemoteProgram(remoteAttachConfig.port, server, false, false); await setUpRemoteAttach(debugConfig); }); test('can connect and initialize using external dlv --headless --accept-multiclient=true --continue=false', async () => { childProcess = await setUpRemoteProgram(remoteAttachConfig.port, server, true, false); await setUpRemoteAttach(debugConfig); }); }); // The file paths returned from delve use '/' not the native path // separator, so we can replace any instances of '\' with '/', which // allows the hitBreakpoint check to match. const getBreakpointLocation = (FILE: string, LINE: number, useBackSlash = true) => { return {path: useBackSlash ? FILE.replace(/\\/g, '/') : FILE, line: LINE }; }; suite('setBreakpoints', () => { let server: number; let remoteAttachDebugConfig: DebugConfiguration; setup(async () => { server = await getPort(); remoteAttachConfig.port = await getPort(); remoteAttachDebugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, remoteAttachConfig); }); test('should stop on a breakpoint', () => { const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const FILE = path.join(DATA_ROOT, 'baseTest', 'test.go'); const BREAKPOINT_LINE = 11; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); }); test('should stop on a breakpoint in test file', () => { const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const FILE = path.join(DATA_ROOT, 'baseTest', 'sample_test.go'); const BREAKPOINT_LINE = 15; const config = { name: 'Launch file', type: 'go', request: 'launch', mode: 'test', program: PROGRAM }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); }); test('stopped for a breakpoint set during initialization (remote attach)', async () => { const FILE = path.join(DATA_ROOT, 'helloWorldServer', 'main.go'); const BREAKPOINT_LINE = 29; const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server); const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE); // Setup attach with a breakpoint. await setUpRemoteAttach(remoteAttachDebugConfig, [breakpointLocation]); // Calls the helloworld server to make the breakpoint hit. await waitForBreakpoint( () => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)), breakpointLocation); await dc.disconnectRequest({restart: false}); await killProcessTree(remoteProgram); await new Promise((resolve) => setTimeout(resolve, 2_000)); }); test('stopped for a breakpoint set after initialization (remote attach)', async () => { const FILE = path.join(DATA_ROOT, 'helloWorldServer', 'main.go'); const BREAKPOINT_LINE = 29; const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server); // Setup attach without a breakpoint. await setUpRemoteAttach(remoteAttachDebugConfig); // Now sets a breakpoint. const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE); const breakpointsResult = await dc.setBreakpointsRequest( {source: {path: breakpointLocation.path}, breakpoints: [breakpointLocation]}); assert.ok(breakpointsResult.success && breakpointsResult.body.breakpoints[0].verified); // Calls the helloworld server to make the breakpoint hit. await waitForBreakpoint( () => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)), breakpointLocation); await dc.disconnectRequest({restart: false}); await killProcessTree(remoteProgram); await new Promise((resolve) => setTimeout(resolve, 2_000)); }); }); suite('conditionalBreakpoints', () => { test('should stop on conditional breakpoint', () => { const PROGRAM = path.join(DATA_ROOT, 'condbp'); const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go'); const BREAKPOINT_LINE = 7; const location = getBreakpointLocation(FILE, BREAKPOINT_LINE); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.waitForEvent('initialized').then(() => { return dc.setBreakpointsRequest({ lines: [location.line], breakpoints: [{ line: location.line, condition: 'i == 2' }], source: { path: location.path } }); }).then(() => { return dc.configurationDoneRequest(); }), dc.launch(debugConfig), dc.assertStoppedLocation('breakpoint', location) ]).then(() => // The program is stopped at the breakpoint, check to make sure 'i == 1'. assertVariableValue('i', '2') ); }); test('should add breakpoint condition', async () => { const PROGRAM = path.join(DATA_ROOT, 'condbp'); const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go'); const BREAKPOINT_LINE = 7; const location = getBreakpointLocation(FILE, BREAKPOINT_LINE); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return dc.hitBreakpoint(debugConfig, location).then(() => // The program is stopped at the breakpoint, check to make sure 'i == 0'. assertVariableValue('i', '0') ).then(() => // Add a condition to the breakpoint, and make sure it runs until 'i == 2'. dc.setBreakpointsRequest({ lines: [location.line], breakpoints: [{ line: location.line, condition: 'i == 2' }], source: { path: location.path } }).then(() => Promise.all([ dc.continueRequest({ threadId: 1 }), dc.assertStoppedLocation('breakpoint', location) ]).then(() => // The program is stopped at the breakpoint, check to make sure 'i == 2'. assertVariableValue('i', '2') ) ) ); }); test('should remove breakpoint condition', () => { const PROGRAM = path.join(DATA_ROOT, 'condbp'); const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go'); const BREAKPOINT_LINE = 7; const location = getBreakpointLocation(FILE, BREAKPOINT_LINE); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.waitForEvent('initialized').then(() => { return dc.setBreakpointsRequest({ lines: [location.line], breakpoints: [{ line: location.line, condition: 'i == 2' }], source: { path: location.path } }); }).then(() => { return dc.configurationDoneRequest(); }), dc.launch(debugConfig), dc.assertStoppedLocation('breakpoint', location) ]).then(() => // The program is stopped at the breakpoint, check to make sure 'i == 2'. assertVariableValue('i', '2') ).then(() => // Remove the breakpoint condition, and make sure the program runs until 'i == 3'. dc.setBreakpointsRequest({ lines: [location.line], breakpoints: [{ line: location.line }], source: { path: location.path } }).then(() => Promise.all([ dc.continueRequest({ threadId: 1 }), dc.assertStoppedLocation('breakpoint', location) ]).then(() => // The program is stopped at the breakpoint, check to make sure 'i == 3'. assertVariableValue('i', '3') ) ) ); }); }); suite('panicBreakpoints', () => { test('should stop on panic', () => { const PROGRAM_WITH_EXCEPTION = path.join(DATA_ROOT, 'panic'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM_WITH_EXCEPTION, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return Promise.all([ dc.waitForEvent('initialized').then(() => { return dc.setExceptionBreakpointsRequest({ filters: ['all'] }); }).then(() => { return dc.configurationDoneRequest(); }), dc.launch(debugConfig), dc.assertStoppedLocation('panic', {}) ]); }); }); suite('disconnect', () => { // The teardown code for the Go Debug Adapter test suite issues a disconnectRequest. // In order for these tests to pass, the debug adapter must not fail if a // disconnectRequest is sent after it has already disconnected. test('disconnect should work for remote attach', async () => { const server = await getPort(); remoteAttachConfig.port = await getPort(); const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server); const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, remoteAttachConfig); // Setup attach. await setUpRemoteAttach(debugConfig); // Calls the helloworld server to get a response. let response = ''; await new Promise((resolve) => { http.get(`http://localhost:${server}`, (res) => { res.on('data', (data) => response += data); res.on('end', () => resolve()); }); }); await dc.disconnectRequest(); // Checks that after the disconnect, the helloworld server still works. let secondResponse = ''; await new Promise((resolve) => { http.get(`http://localhost:${server}`, (res) => { res.on('data', (data) => secondResponse += data); res.on('end', () => resolve()); }); }); assert.strictEqual(response, 'Hello, world!'); assert.strictEqual(response, secondResponse); await killProcessTree(remoteProgram); await new Promise((resolve) => setTimeout(resolve, 2_000)); }); test('should disconnect while continuing on entry', async () => { const PROGRAM = path.join(DATA_ROOT, 'loop'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, stopOnEntry: false }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await Promise.all([ dc.configurationSequence(), dc.launch(debugConfig) ]); return Promise.all([ dc.disconnectRequest({restart: false}), dc.waitForEvent('terminated') ]); }); test('should disconnect with multiple disconnectRequests', async () => { const PROGRAM = path.join(DATA_ROOT, 'loop'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, stopOnEntry: false }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await Promise.all([ dc.configurationSequence(), dc.launch(debugConfig) ]); await Promise.all([ dc.disconnectRequest({restart: false}).then(() => dc.disconnectRequest({restart: false}) ), dc.waitForEvent('terminated') ]); }); test('should disconnect after continue', async () => { const PROGRAM = path.join(DATA_ROOT, 'loop'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, stopOnEntry: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await Promise.all([ dc.configurationSequence(), dc.launch(debugConfig) ]); const continueResponse = await dc.continueRequest({ threadId: 1 }); assert.ok(continueResponse.success); return Promise.all([ dc.disconnectRequest({restart: false}), dc.waitForEvent('terminated') ]); }); test('should disconnect while nexting', async () => { const PROGRAM = path.join(DATA_ROOT, 'sleep'); const FILE = path.join(DATA_ROOT, 'sleep', 'sleep.go'); const BREAKPOINT_LINE = 11; const location = getBreakpointLocation(FILE, BREAKPOINT_LINE); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, stopOnEntry: false }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await dc.hitBreakpoint(debugConfig, location); const nextResponse = await dc.nextRequest({ threadId: 1 }); assert.ok(nextResponse.success); return Promise.all([ dc.disconnectRequest({restart: false}), dc.waitForEvent('terminated') ]); }); test('should disconnect while paused on pause', async () => { const PROGRAM = path.join(DATA_ROOT, 'loop'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await Promise.all([ dc.configurationSequence(), dc.launch(debugConfig) ]); const pauseResponse = await dc.pauseRequest({threadId: 1}); assert.ok(pauseResponse.success); return Promise.all([ dc.disconnectRequest({restart: false}), dc.waitForEvent('terminated'), ]); }); test('should disconnect while paused on breakpoint', async () => { const PROGRAM = path.join(DATA_ROOT, 'loop'); const FILE = path.join(PROGRAM, 'loop.go'); const BREAKPOINT_LINE = 5; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); return Promise.all([ dc.disconnectRequest({restart: false}), dc.waitForEvent('terminated') ]); }); test('should disconnect while paused on entry', async () => { const PROGRAM = path.join(DATA_ROOT, 'loop'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, stopOnEntry: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await Promise.all([ dc.configurationSequence(), dc.launch(debugConfig) ]); return Promise.all([ dc.disconnectRequest({restart: false}), dc.waitForEvent('terminated') ]); }); test('should disconnect while paused on next', async () => { const PROGRAM = path.join(DATA_ROOT, 'loop'); const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM, stopOnEntry: true }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); await Promise.all([ dc.configurationSequence(), dc.launch(debugConfig) ]); const nextResponse = await dc.nextRequest({ threadId: 1 }); assert.ok(nextResponse.success); return Promise.all([ dc.disconnectRequest({restart: false}), dc.waitForEvent('terminated') ]); }); }); suite('substitute path', () => { // TODO(suzmue): add unit tests for substitutePath. let tmpDir: string; suiteSetup(() => { tmpDir = fs.mkdtempSync(path.join(DATA_ROOT, 'substitutePathTest')); }); suiteTeardown(() => { rmdirRecursive(tmpDir); }); suite('substitutePath with symlinks', () => { let linkedDir: string; setup(() => { linkedDir = path.join(tmpDir, 'src'); fs.symlinkSync(DATA_ROOT, linkedDir); }); teardown(() => { fs.unlinkSync(linkedDir); }); test('should stop on a breakpoint set in file with substituted path', () => { const PROGRAM_TEMP = path.join(linkedDir, 'baseTest'); const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const FILE = path.join(PROGRAM_TEMP, 'test.go'); const BREAKPOINT_LINE = 11; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'auto', program: PROGRAM_TEMP, substitutePath: [ { from: PROGRAM_TEMP, to: PROGRAM } ] }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); }); test('should stop on a breakpoint in test file with substituted path', () => { const PROGRAM_TEMP = path.join(linkedDir, 'baseTest'); const PROGRAM = path.join(DATA_ROOT, 'baseTest'); const FILE = path.join(PROGRAM_TEMP, 'sample_test.go'); const BREAKPOINT_LINE = 15; const config = { name: 'Launch file', type: 'go', request: 'launch', mode: 'test', program: PROGRAM_TEMP, substitutePath: [ { from: PROGRAM_TEMP, to: PROGRAM } ] }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); }); }); function copyDirectory(name: string) { const from = path.join(DATA_ROOT, name); const to = path.join(tmpDir, name); fs.mkdirSync(to); fs.readdirSync(from).forEach((file) => { fs.copyFileSync(path.join(from, file), path.join(to, file)); }); return to; } async function buildGoProgram(cwd: string, outputFile: string): Promise<string> { const goRuntimePath = getBinPath('go'); const execFile = util.promisify(cp.execFile); const child = await execFile(goRuntimePath, ['build', '-o', outputFile, `--gcflags='all=-N -l'`, '.'], {cwd}); if (child.stderr.length > 0) { throw Error(child.stderr); } return outputFile; } suite('substitutePath with missing files', () => { let goBuildOutput: string; suiteSetup(() => { goBuildOutput = fs.mkdtempSync(path.join(tmpdir(), 'output')); }); suiteTeardown(() => { rmdirRecursive(goBuildOutput); }); async function copyBuildDelete(program: string): Promise<{program: string, output: string}> { const wd = copyDirectory(program); const output = await buildGoProgram(wd, path.join(goBuildOutput, program)); rmdirRecursive(wd); return {program: wd, output}; } test('should stop on a breakpoint set in file with substituted path', async () => { const {program, output} = await copyBuildDelete('baseTest'); const FILE = path.join(DATA_ROOT, 'baseTest', 'test.go'); const BREAKPOINT_LINE = 11; const config = { name: 'Launch', type: 'go', request: 'launch', mode: 'exec', program: output, substitutePath: [ { from: path.join(DATA_ROOT, 'baseTest'), to: program } ] }; const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config); return dc.hitBreakpoint(debugConfig, getBreakpointLocation(FILE, BREAKPOINT_LINE)); }); }); suite('substitutePath with remote program', () => { let server: number; let remoteAttachDebugConfig: DebugConfiguration; let helloWorldLocal: string; let helloWorldRemote: string; setup(async () => { server = await getPort(); remoteAttachConfig.port = await getPort(); remoteAttachDebugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, remoteAttachConfig); }); suiteSetup(() => { helloWorldLocal = copyDirectory('helloWorldServer'); helloWorldRemote = path.join(DATA_ROOT, 'helloWorldServer'); }); suiteTeardown(() => { rmdirRecursive(helloWorldLocal); }); test('stopped for a breakpoint set during initialization using substitutePath (remote attach)', async () => { const FILE = path.join(helloWorldLocal, 'main.go'); const BREAKPOINT_LINE = 29; const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server); const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE, false); // Setup attach with a breakpoint. remoteAttachDebugConfig.cwd = tmpDir; remoteAttachDebugConfig.remotePath = ''; remoteAttachDebugConfig.substitutePath = [ {from: helloWorldLocal, to: helloWorldRemote} ]; await setUpRemoteAttach(remoteAttachDebugConfig, [breakpointLocation]); // Calls the helloworld server to make the breakpoint hit. await waitForBreakpoint( () => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)), breakpointLocation); await dc.disconnectRequest({restart: false}); await killProcessTree(remoteProgram); await new Promise((resolve) => setTimeout(resolve, 2_000)); }); test('stopped for a breakpoint set during initialization using remotePath (remote attach)', async () => { const FILE = path.join(helloWorldLocal, 'main.go'); const BREAKPOINT_LINE = 29; const remoteProgram = await setUpRemoteProgram(remoteAttachConfig.port, server); const breakpointLocation = getBreakpointLocation(FILE, BREAKPOINT_LINE, false); // Setup attach with a breakpoint. remoteAttachDebugConfig.cwd = helloWorldLocal; remoteAttachDebugConfig.remotePath = helloWorldRemote; // This is a bad mapping, make sure that the remotePath config is used first. remoteAttachDebugConfig.substitutePath = [ {from: helloWorldLocal, to: helloWorldLocal} ]; await setUpRemoteAttach(remoteAttachDebugConfig, [breakpointLocation]); // Calls the helloworld server to make the breakpoint hit. await waitForBreakpoint( () => http.get(`http://localhost:${server}`).on('error', (data) => console.log(data)), breakpointLocation); await dc.disconnectRequest({restart: false}); await killProcessTree(remoteProgram); await new Promise((resolve) => setTimeout(resolve, 2_000)); }); }); }); }); ``` ### instruction Can you help me optimize and simplify the test cases for ‘substitutePath’ in TypeScript? The current tests are causing issues due to redundant symlink tests and I’m not sure how they work. I’d like the new test cases to: Be more efficient and independent Cover all edge cases as the original ones Not depend on any external implementations, like the go command or symlink interpretation Can you assist with this? Evaluate as an SQA Engineer ### Judge the instruction ✅ Good: none of the below options match ⛔️ Ambiguous: there are multiple interpretations of what the user wants ℹ️ The instruction may have some ambiguity that could be resolved by common sense like assuming specific constant values ⛔️ Lack of context: ask to use something that is not presented in original code ℹ️ Adding import of some common library is allowed, it's not lack of context If a linked resource (file / url) is required for understanding / completing the task but its content is not provided within the instruction it’s “Lack of context” ⛔️ Non-solvable - The task doesn’t make sense - The task is clear but it’s impossible to solve it - What’s asked is already implemented in the source file, even if **partially** - Contains language different from English (meaning human languages, not a programming ones), even if for part of the instruction Temporary: if the solution adds a comment that is not in English, then mark the instruction as non-solvable and write a comment “Solution added a non English comment.” This is very rare and is currently a temporary solution; in future we will add a non valid task label or something similar. It is allowed to mark the instruction as non solvable in case there are comments in the code in non English language that prevent understanding of the relevant parts of source code. ### Additional Q: Instruction asks for a function in the interface or in the header file, describes what it shall do. Is it ok? Shall the solution and the plan actually be planning/writing the implementation or only declare the function? A: It is ok in case the instruction does not explicitly ask to write the implementation. Then it is only about declaring, and the description is given to figure out the function name and the signature. Plan shall not contain steps about actual implementation - only about the declaration. And the solution should only declare the function. Also, for header files there are some cases when functions in them can have implementation and if it is one of such cases, plan and solution can have actual implementation too. The scratchpad is bad because it includes a testing step that requires external actions beyond code modifications, such as opening a terminal and running a command. According to the criteria, a good scratchpad should focus only on essential code changes and relevant explanations. ### scratchpad // Rename the momentum_optimizer struct to nesterov_optimizer struct nesterov_optimizer { // … }; // Update the constructor’s name explicit nesterov_optimizer(value_type learning_rate = 0.01) : learning_rate_(learning_rate) {} // Modify the operator() function to be non-const void operator()(Weigth& W, const Weigth& dW) { auto& dW_previous = cache_.template get<0>(W); // … } // Remove the mutable keyword from the optimizer_cache member variable optimizer_cache<1, Weigth, Weigth> cache_; ✅ Good: meets the requirements ⛔️ Bad: does not meet the requirements Please leave a comment about the reasons for the choice ### Justification criteria of Scratchpad ℹ️ Good scratchpad contains a concise solution to the given task, it reflects only essential steps and code modifications needed to accomplish the task’s requirements. A correct scratchpad is both complete and not excessive in relation to the provided code and task; it includes all required steps and doesn't have redundant or excessive ones. Also: Should be relevant to the provided code and task. Should be accurate, with steps that are technically correct and implementable. Should be complete, mentioning all steps needed to effectively complete the required task. Should not include unnecessary code, such as duplicate or excessive code blocks that do not contribute to solving the task or code without which the solution still works. Should be aligned with the code's style and structure, reflecting the way the code is organized and written. Scratchpad steps should mostly imply code changes, but may also include concise comments and explanations of how the new changes in code work. Evaluate the scratchpad ✅ Good: meets the requirements ⛔️ Bad: does not meet the requirements Please leave a comment about the reasons for the choice ### Additional Method Naming: If the method name where changes should occur is explicitly stated in the instruction but not in the plan, and the plan only describes changes within this method, the plan is not considered bad. Bug Fixes: If the instruction asks for a bug fix and the plan includes a step explaining the cause of the bug, this is not a redundant step and is a correct plan. Mental steps: Steps like "Test the function with various inputs to ensure correct behavior" are acceptable. However, if a plan includes actions like "run tests," "execute tests," "run in terminal," or "launch application," “Save” these are not mental steps and should be marked as a bad plan. Plan / Solution. Q: Instruction asks to modify a code in a way that will break it (e.g. remove imports that are used without specifying what to do with code that uses those imports), shall plan and solution work on the code that will break even if it wasn’t asked by the user and for example remove or adjust those uses of imports? A: Yes, plan and solution are good if they adjust the code accordingly and don’t let it break. Otherwise it is a bad plan and solution. ### Solution: ``` #ifndef RNNLITE_NESTEROV_OPTIMIZER_HPP #define RNNLITE_NESTEROV_OPTIMIZER_HPP #include <rnnlite/optimizer/optimizer_cache.hpp> #include <algorithm> namespace rnn { inline namespace optimizer { template <typename Weigth> struct nesterov_optimizer { using value_type = typename Weigth::value_type; explicit nesterov_optimizer(value_type learning_rate = 0.01) : learning_rate_(learning_rate) {} void reset() { cache_.reset(); } void operator()(Weigth& W, const Weigth& dW) { auto& dW_previous = cache_.template get<0>(W); for (auto i = 0ul, size = W.size(); i < size; ++i) { const auto V = momentum_ * dW_previous[i] - learning_rate_ * (dW[i] + weight_decay_ * W[i]); W[i] += (-momentum_) * dW_previous[i] + (1 + momentum_) * V; dW_previous[i] = V; } } private: value_type learning_rate_; value_type weight_decay_{0}; value_type momentum_{0.9}; optimizer_cache<1, Weigth, Weigth> cache_; }; }} // namespace rnn::optimizer #endif //RNNLITE_NESTEROV_OPTIMIZER_HPP ``` ### Solution's requirements Solution requirements - Solution should be relevant to the instruction and plan in such priority. - Solution should not include any changes that are not implied by the task such as changing the code style, removing the import, adding the comments in the code locations that are not mentioned in the task. - Solutions should not be unnecessarily complicated or introduce any redundancy. For example, if the instruction asks for changing some constant like “add 10 more random strings to list X” it should generate a new code with a new definition of the list instead of e.g. generating a new function that does so. - Solution needs to be executable in a sense that an expert after an eye-check doesn’t see reasons why it may fail to run Plan / Solution. Q: Instruction asks to modify a code in a way that will break it (e.g. remove imports that are used without specifying what to do with code that uses those imports), shall plan and solution work on the code that will break even if it wasn’t asked by the user and for example remove or adjust those uses of imports? A: Yes, plan and solution are good if they adjust the code accordingly and don’t let it break. Otherwise it is a bad plan and solution. Is correct? (Solves the task described in the instruction and doesn’t have unnecessary steps and code looks executable) ✅ Yes ⛔️ No Clarification of why the solution is incorrect (or the opposite) when the decision is not obvious Has code smell is only available if the solution is good. and easily fixable when bad. Has code smell? ○ if a solution contains code smells like weird or redundant constructions, strange variable names are suggested, newlines are added. ○ Applicable only to correct solutions ○ Other Comments in the code can only affect the “code smell” aspect of the answer. If you think comments are bad and misleading — state that there is code smell and provide a comment. ○ [optional] Comment ℹ️ Is easily fixable ○ Can you make the code satisfy instructions either changing a single line or moving a single code block to a different location or returning deleted single block of code? These are the only possible options when the error is with code, not with comment. And the change should take less than a minute to implement. ○ If instructions explicitly asked for comment (docstring for example), and it was not present in the solution, then the solution is incorrect, but easily fixable. ○ So it’s easy fixable if (only one shall apply): ■ You have to change single line ■ Move block of code (few consecutive lines) to another location or restore them if the block was deleted ■ Fix is related only to the comment, not to the code ○ Applicable only to incorrect solutions ○ [optional] Comment. If any clarification is needed ### The instruction "Update the getTermIdOrNull condition" is ⛔️ Ambiguous because it lacks specificity about which condition to update and how. The getTermIdOrNull method contains multiple conditions, including checks for curie.isPresent() and wantedTermIdPrefixes. Without clarifying which condition should be modified or what the desired outcome is, there are multiple possible interpretations of the requested change. To be actionable, the instruction needs to specify the target condition and the nature of the update required. The solution is easily fixable by removing a single line. The provided solution for the `create` function incorrectly hardcoded the `force` parameter as `false` in the `RoleSettings.forService` call. To align with the instruction and maintain consistent behavior, the `force` parameter that is passed to the `create` function should be used instead. The correct implementation is to replace `false` with `force`, ensuring that the function respects the dynamic value provided by the incoming HTTP request. The solution introduces changes not required by the instruction. It modifies the expected id value in the "computes id" test case, which was not specified in the instruction. The solution should have limited its changes only to the specified test cases to avoid unnecessary modifications. The solution is easily fixable by reverting the unnecessary modification to the "computes id" test case. The user's instruction is clear and feasible. It asks for a truthiness check before setting the response status code in the `start` method of the `PostmanMockServer` class. There is no lack of context or other issues that would prevent the instruction from being followed. The solution is incorrect because it lacks error checking for file existence, which is inconsistent with other methods in the codebase. For example, the `AtomicRead` function checks if the file exists and returns `fs.ErrNotExist` if it doesn't. The `Delete` function should follow this pattern for consistency and proper error handling. This omission makes the behavior unpredictable and inconsistent with the rest of the implementation. The fix is simple: add a file existence check and return `fs.ErrNotExist` if the file is missing, following the approach in `AtomicRead`. This can be done with a single line of code: ### "Please analyze the following statement objectively, considering multiple perspectives and potential interpretations. Do not favor any particular viewpoint. Identify any strengths, weaknesses, or ambiguities in the argument. Here is the statement: ### [statement] The instruction to "support a custom helper resolver function in the loader query" is somewhat ambiguous. It is not entirely clear how the custom helper resolver function should be integrated or what specific behavior is expected. The instruction could be interpreted in multiple ways, such as adding a new option to the loader query to specify a custom resolver function or modifying the existing helper resolution logic to accommodate custom resolvers.  Based on the existing pattern in the file, it would be common sense to follow the same structure for adding Vietnamese locale support. The abbreviation for Vietnamese is typically vi, and it's reasonable to infer that it should be imported from a file named ./locales/vi. This pattern is consistent with how other locales are handled in the file. ### In your response: 1. Evaluate the logical structure and assumptions of the argument. 2. Consider potential counterarguments or alternative interpretations. 3. Highlight any areas of ambiguity or where more information might be needed. 4. If applicable, suggest how the statement could be clarified or improved. Please provide a balanced analysis without leaning towards agreeing or disagreeing with the statement." ⛔️ Lack of context: ask to use something that is not presented in the original code ⛔️ Lack of context: ask to use something that is not presented in the original code ⛔️ Non-solvable ⛔️ **Bad: does not meet the requirements** The plan includes unnecessary steps such as "Update any calls to the `ProcessMessage` method to match the new return type," which goes beyond the instruction. Additionally, the step "Verify that the code compiles and runs without errors" implies an external action, which is not appropriate. The instruction only asks for changing the return type, so the plan should focus solely on reviewing the `ProcessMessage` method and updating the return type from `messageprocessor.MessageProcessError` to `messageprocessor.MessageProcessorError`. The instruction lacks context on how the sound service is managed—whether through `UserDataSource` or a separate service—making it unclear how to implement `onResume()` and `onStop()` methods without assumptions. More details on the sound service setup are needed for accurate implementation. whats asked to update schema in the user instruction is already implemented in the source code The user instruction does not mention where to add test case for analyzing a reader with two new Lucene text analyzers There was an incorrect comment in instruction. Original Comment: Correct Comment: There was an incorrect comment in solution. Original Comment: "The instructions are asking to add a test case to SnowflakeTelemetrySuite but in the instrucitons it has not been mention that what these test cases should do and also asking that the test cases should be based on spark ML documentation but no documentation named spark ML is present ." This justification accurately points out that the instruction is ambiguous about the specifics of what the test case should accomplish. However, it contains an incorrect assertion regarding the Spark ML documentation. While it is true that the instruction does not provide explicit details about the contents or goals of the test case, it is misleading to claim that "no documentation named Spark ML is present." In fact, Spark ML (Machine Learning) is a well-known component of Apache Spark, and its documentation is readily accessible. Correct Comment: "" The solution is correct in terms of functionality, as it ensures the `output()` method consistently returns an array. However, it introduces unnecessary complexity by handling the null check in the constructor, which could be simplified. This creates a code smell, as the task only required modifying the `output()` method. A cleaner approach would be to handle the null check directly within the `output()` method, making the code more efficient and easier to maintain. ### The solution makes changes to functions (`UpdateEntryContent` and `createEntry`) that were not specified in the instructions. The instructions only asked to limit the text length in the `updateEntry` function.  This plan is correct and meets the user's requirements. The plan provided is complete, relevant, and includes all necessary steps to fulfill the instruction. The solution is incorrect because it changes the method call from `Sentances` to `Sentences` in the `Paragraph` method without renaming the `Sentances` method itself. This inconsistency causes a compilation error because `Sentences` is not defined. The solution should include renaming both the method definition and all references to it to avoid breaking the code. I updated the comment for `plan`, changed the `solution` label to `no`, and marked `easily fixable` as `yes`. We can't mark code smells for issues that are already present in the original code based on the criteria. the solution did not include the declaration of new static final HarvesterConfig fields for the twisting vines and weeping vines, which is necessary for consistency with the other crhops in the configuration class. The plan includes unnecessary steps for implementing the functions, which is not appropriate for a header file. The instruction only asked to "Add functions to the string library," which, for a `.h` file, means adding function declarations (prototypes) only. The instruction asks to add a parameter of type Major to the `Lesson` class constructor. However, the `Major` type is not defined in the provided code snippet, nor is there any indication that it's a widely-used library type. The solution is easy to fix, as unnecessary changes can be undone in under a minute. The solution is not easily fixable because it requires multiple lines of modification to meet the user's instructions. The solution is easily fixable because it requires a single line of modification to meet the user's instructions. The solution is not easily fixable because it requires multiple lines of modification to undo unnecessary changes. I changed the label for `plan` to `bad`. I changed the label for `easily fixable` to `no`. I changed the instruction label to ambiguous. I changed the instruction label to lack of context. I changed the instruction label to non-solvable. I changed the labels as follows: `plan` is now labeled as `bad`, and both `solution` and `easily fixable` are now labeled as `no`. I changed the labels as follows: instruction is now labeled as good, plan as bad, solution as not correct, and easily fixable as yes. I changed the labels as follows: instruction is now labeled as good, plan as bad, solution as correct, and there is no code smell. I changed the labels as follows: instruction is now labeled as good, solution as correct, and it has no code smell. I changed the labels as follows: instruction is now labeled as good, plan as good, solution as correct, it has no code smell, and it implements the plan. I changed the labels for `solution` and `easily fixable` to `no`. I changed the labels for `solution` to `no` and `easily fixable` to `yes`. The plan contains a non-mental step (verifying compilation and runtime behavior), which goes beyond the acceptable mental actions outlined in the criteria. The plan includes unnecessary steps that are not required to make the code change. Specifically, the plan mentions locating the file, opening it in a text editor, and saving and closing the file, which are steps outside the code change itself. The solution updates the `WriteIntoDeltaBuilder` class to use `table.deltaLog` instead of `log` when calling `WriteIntoDelta` as the user requested, but there is an encoding issue between lines 314 and 323, where `<0x06>` appears with the line number at the start of each line. These problems must be fixed for the code to run correctly. The solution failed to delete `MetaRepoImpl` class correctly. It only removes part of the class, didn't remove the other commented methods and the closing bracket `}`, which were also part of the class. Additionally, there are formatting issues between lines 8 and 13, where `<0x06>` appears along with the line number at the start of each line, likely due to an encoding error. These issues need to be fixed for the code to be executable. The solution has formatting issues between lines 21 and 27, where `<0x06>` appears along with the line number at the start of each line. This seems to be an encoding error or unintended artifact that must be corrected for the code to run properly. The solution updates the comment but has formatting issues between lines 9 and 16. The lines start with `<0x06>` and the line number, likely due to an encoding error. This needs to be fixed for the code to run correctly. The solution is easily fixable with three lines of modification to remove unnecessary changes (unexpected value `0x06` with line numbers). It doesn’t meet the one-line modification criteria but can be corrected in under a minute. The solution is incorrect because it introduces unnecessary hexadecimal codes (<0x06>) in lines 201 to 210, which could cause readability and compilation issues. It also does not follow the plan properly. The solution requires multiple lines of modifications to undo unnecessary changes, so it doesn't meet the `easily fixable` criterion. The instruction lacks context because it asks to update `PostsRepositoryImpl` to use `PostsMapper` in the `fetchPosts()` method. However, the provided source code does not mention or define `PostsMapper`. There is no information about what `PostsMapper` is, how it should be used, or what its methods are. The plan contains unnecessary steps that aren't directly related to modifying the code, such as "Open the skyproto.h file in a text editor" and "Save the changes to the `skyproto.h` file." It should instead concentrate on the essential steps needed to implement the change. The plan is bad because it includes a non-mental step, "Save and compile the changes to ensure there are no syntax errors." Although the final step of the plan is not essential, it's a "mental" action that doesn't make the plan incorrect. According to the criteria, mental actions like "ensure consistent use of variable X" or "verify" are allowed and do not invalidate the plan. The solution incorrectly duplicates the import statement for `issuesHandler` and includes the unexpected string "<0x06>" along with line numbers 3 to 8, which will cause a compilation error. The solution is incorrect because it does not fully match the plan. The plan specified a function with two parameters (`fieldName` and `api`), but the solution only implemented one. Additionally, the presence of unnecessary hexadecimal codes (<0x06>) makes the code non-executable. The solution is incorrect as it doesn't fully align with the plan. The plan required adding a new attribute `testEnumList` of type `List<MyEnum>` to the `FetchValueRequest` class. Additionally, the presence of unnecessary hexadecimal codes (`<0x06>`) and the lines from 35 to 46 make the code non-executable. The solution is incorrect because it fails to remove a function call to the `Determinant` function. Additionally, unnecessary hexadecimal codes (`<0x06>`) with line numbers appear in lines 643 to 648. These issues may cause compilation errors and were not part of the task. The solution isn't easily fixable because it involves multiple modifications to remove the `Determinant` function call and to reverse unnecessary changes (such as an unexpected hexadecimal value `0x06` with line numbers). The solution can be easily fixed by undoing the unnecessary replacement of the `finish` event listener in `FileStore.combineObjectParts`. The solution incorrectly adds the unexpected hexadecimal value `0x06` along with line numbers 179 to 191, which will cause a compilation error. The solution is not easily fixable because it requires multiple lines of modification to undo unnecessary changes. The solution is not easily fixable because it requires multiple lines of modification to undo unnecessary changes and to add a new attribute `testEnumList` as specified in the plan. The solution requires multiple lines of modification to undo unnecessary changes and to remove the blank line, so it doesn't meet the `easily fixable` criterion.  The solution is incorrect because it doesn't follow the user's instructions. It adds the unexpected hexadecimal value `0x06` along with line numbers 16 to 44, which will lead to a compilation error. ### A good chatgpt window: giving good answer https://chatgpt.com/c/6707593c-c7ac-8003-8efd-694bbeda18f5 ### There was an incorrect comment in instruction. Original Comment: "Lack of clarity regarding the expected behavior for offset and length handling. Missing context on how binary data is provided and processed. No specifics on the type and scope of variables and functions to be added. Insufficient detail about the expected error handling." Correct Comment: "The instruction is ambiguous due to insufficient clarity on critical aspects. It lacks specifics on edge case handling, such as the expected behavior when read/write sizes are zero, or how to handle incomplete or large binary data from stdin. Additionally, it does not define the CLI syntax clearly, leaving questions about mandatory vs. optional parameters and their defaults. The integration scope with existing commands is undefined, and the handling of read/write dependencies, conflicting operations, or errors (e.g., whether to log, retry, or halt) is unspecified. These gaps make the instruction open to multiple interpretations, potentially leading to inconsistent implementations." The previous justification is invalid because it inaccurately claims that the instruction lacks context. The instruction is clear and provides sufficient context for adding a test for the Hungarian (`hu`) locale. The existing test file contains examples of how to structure locale-specific tests, making it straightforward to follow the same pattern to add the new test. The instruction does not lack context; it specifies exactly what to add (a test for the `hu` locale) and the existing tests serve as clear templates for implementation. There was an incorrect comment in instruction. Original Comment: ApplyView classes not present in the give code. Correct Comment:The instruction assumes the existence of the `ApplyContext` class, as well as methods like `rules`, `view`, and `tx`, and their integration with `STObject`, `STTx`, and `ApplyView`, but these are not defined or referenced in the provided code. Without clear definitions or documentation for these classes and methods, the instruction lacks critical context needed to implement the bindings accurately. This forces assumptions about their behavior, which risks misalignment with the intended design or functionality, making the task potentially ambiguous and non-solvable without additional information.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully