From ca0fa174f3de6587b344d221f253f6aa0becba2e Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:46:45 -0700 Subject: [PATCH 01/13] flask and django tests --- src/test/debugger/web.framework.test.ts | 153 ++++++++++++++++++ .../workspace5/djangoApp/home/__init__.py | 0 .../djangoApp/home/templates/index.html | 9 ++ .../workspace5/djangoApp/home/urls.py | 7 + .../workspace5/djangoApp/home/views.py | 10 ++ .../workspace5/djangoApp/manage.py | 22 +++ .../workspace5/djangoApp/mysite/__init__.py | 0 .../workspace5/djangoApp/mysite/settings.py | 93 +++++++++++ .../workspace5/djangoApp/mysite/urls.py | 23 +++ .../workspace5/djangoApp/mysite/wsgi.py | 16 ++ .../workspace5/flaskApp/run.py | 13 ++ .../workspace5/flaskApp/templates/index.html | 9 ++ 12 files changed, 355 insertions(+) create mode 100644 src/test/debugger/web.framework.test.ts create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/__init__.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/home/views.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/manage.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/__init__.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py create mode 100644 src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py create mode 100644 src/testMultiRootWkspc/workspace5/flaskApp/run.py create mode 100644 src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts new file mode 100644 index 000000000000..e4f752678664 --- /dev/null +++ b/src/test/debugger/web.framework.test.ts @@ -0,0 +1,153 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal + +import { expect } from 'chai'; +import * as fs from 'fs'; +import * as getFreePort from 'get-port'; +import * as path from 'path'; +import { DebugClient } from 'vscode-debugadapter-testsupport'; +import { EXTENSION_ROOT_DIR } from '../../client/common/constants'; +import { noop } from '../../client/common/core.utils'; +import { DebugOptions, LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; +import { sleep } from '../common'; +import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; +import { DEBUGGER_TIMEOUT } from './common/constants'; +import { continueDebugging, createDebugAdapter, ExpectedVariable, hitHttpBreakpoint, makeHttpRequest, validateVariablesInFrame } from './utils'; + +let testCounter = 0; +const debuggerType = 'pythonExperimental'; +suite(`Django and Flask Debugging: ${debuggerType}`, () => { + let debugClient: DebugClient; + setup(async function () { + if (!IS_MULTI_ROOT_TEST || !TEST_DEBUGGER) { + this.skip(); + } + this.timeout(5 * DEBUGGER_TIMEOUT); + const coverageDirectory = path.join(EXTENSION_ROOT_DIR, `debug_coverage_django_flask${testCounter += 1}`); + debugClient = await createDebugAdapter(coverageDirectory); + }); + teardown(async function () { + if (this.currentTest.state !== 'passed') { + console.log(this.currentTest.title); + console.log(fs.readFileSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log')).toString()); + } + // Wait for a second before starting another test (sometimes, sockets take a while to get closed). + await sleep(1000); + try { + await debugClient.stop().catch(noop); + // tslint:disable-next-line:no-empty + } catch (ex) { } + await sleep(1000); + }); + function buildLaunchArgs(workspaceDirectory: string): LaunchRequestArguments { + const env = {}; + // tslint:disable-next-line:no-string-literal + env['PYTHONPATH'] = path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'experimental', 'ptvsd'); + + // tslint:disable-next-line:no-unnecessary-local-variable + const options: LaunchRequestArguments = { + cwd: workspaceDirectory, + program: '', + debugOptions: [DebugOptions.RedirectOutput], + pythonPath: 'python', + args: [], + env, + envFile: '', + logToFile: true, + type: debuggerType + }; + + return options; + } + async function buildFlaskLaunchArgs(workspaceDirectory: string) { + const port = await getFreePort({ host: 'localhost' }); + const options = buildLaunchArgs(workspaceDirectory); + + options.env!['FLASK_APP'] = path.join(workspaceDirectory, 'run.py'); + options.module = 'flask'; + options.debugOptions = [DebugOptions.RedirectOutput, DebugOptions.Jinja]; + options.args = [ + 'run', + '--no-debugger', + '--no-reload', + '--port', + `${port}` + ]; + + return { options, port }; + } + async function buildDjangoLaunchArgs(workspaceDirectory: string) { + const port = await getFreePort({ host: 'localhost' }); + const options = buildLaunchArgs(workspaceDirectory); + + options.program = path.join(workspaceDirectory, 'manage.py'); + options.debugOptions = [DebugOptions.RedirectOutput, DebugOptions.Django]; + options.args = [ + 'runserver', + '--noreload', + '--nothreading', + `${port}` + ]; + + return { options, port }; + } + + async function testTemplateDebugging(launchArgs: LaunchRequestArguments, port: number, viewFile: string, viewLine: number, templateFile: string, templateLine: number) { + await Promise.all([ + debugClient.configurationSequence(), + debugClient.launch(launchArgs), + debugClient.waitForEvent('initialized'), + debugClient.waitForEvent('process'), + debugClient.waitForEvent('thread') + ]); + + const httpResult = await makeHttpRequest(`http://localhost:${port}`); + + expect(httpResult).to.contain('Hello this_is_a_value_from_server'); + expect(httpResult).to.contain('Hello this_is_another_value_from_server'); + + await hitHttpBreakpoint(debugClient, `http://localhost:${port}`, viewFile, viewLine); + + await continueDebugging(debugClient); + await debugClient.setBreakpointsRequest({ breakpoints: [], lines: [], source: { path: viewFile } }); + + // Template debugging. + const [stackTrace, htmlResultPromise] = await hitHttpBreakpoint(debugClient, `http://localhost:${port}`, templateFile, templateLine); + + // Wait for breakpoint to hit + const expectedVariables: ExpectedVariable[] = [ + { name: 'value_from_server', type: 'str', value: '\'this_is_a_value_from_server\'' }, + { name: 'another_value_from_server', type: 'str', value: '\'this_is_another_value_from_server\'' } + ]; + await validateVariablesInFrame(debugClient, stackTrace, expectedVariables, 1); + + await debugClient.setBreakpointsRequest({ breakpoints: [], lines: [], source: { path: templateFile } }); + await continueDebugging(debugClient); + + const htmlResult = await htmlResultPromise; + expect(htmlResult).to.contain('Hello this_is_a_value_from_server'); + expect(htmlResult).to.contain('Hello this_is_another_value_from_server'); + } + + test('Test Flask Route and Template debugging', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); + const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); + + await testTemplateDebugging(options, port, + path.join(workspaceDirectory, 'run.py'), 7, + path.join(workspaceDirectory, 'templates', 'index.html'), 6); + }); + + test('Test Django Route and Template debugging', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); + const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); + + await testTemplateDebugging(options, port, + path.join(workspaceDirectory, 'home', 'views.py'), 10, + path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); + }); +}); diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/__init__.py b/src/testMultiRootWkspc/workspace5/djangoApp/home/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html b/src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html new file mode 100644 index 000000000000..6ca5107d23d6 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/home/templates/index.html @@ -0,0 +1,9 @@ + + + + +

Hello {{ value_from_server }}!

+

Hello {{ another_value_from_server }}!

+ + + diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py b/src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py new file mode 100644 index 000000000000..70a9606e88e6 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/home/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url('', views.index, name='index'), +] diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/home/views.py b/src/testMultiRootWkspc/workspace5/djangoApp/home/views.py new file mode 100644 index 000000000000..0494f868dc6f --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/home/views.py @@ -0,0 +1,10 @@ +from django.shortcuts import render +from django.template import loader + + +def index(request): + context = { + 'value_from_server':'this_is_a_value_from_server', + 'another_value_from_server':'this_is_another_value_from_server' + } + return render(request, 'index.html', context) diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/manage.py b/src/testMultiRootWkspc/workspace5/djangoApp/manage.py new file mode 100644 index 000000000000..afbc784aafd8 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/__init__.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py new file mode 100644 index 000000000000..4e182517ca2a --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/settings.py @@ -0,0 +1,93 @@ +""" +Django settings for mysite project. + +Generated by 'django-admin startproject' using Django 1.11.2. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.11/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '5u06*)07dvd+=kn)zqp8#b0^qt@*$8=nnjc&&0lzfc28(wns&l' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['localhost', '127.0.0.1'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.contenttypes', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ +] + +ROOT_URLCONF = 'mysite.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': ['home/templates'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'mysite.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ +] + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.11/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py new file mode 100644 index 000000000000..9db383365e3e --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/urls.py @@ -0,0 +1,23 @@ +"""mysite URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url, include +from django.contrib import admin +from django.views.generic import RedirectView + +urlpatterns = [ + url(r'^home/', include('home.urls')), + url('', RedirectView.as_view(url='/home/')), +] diff --git a/src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py new file mode 100644 index 000000000000..74e7daeefe76 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/djangoApp/mysite/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for mysite project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") + +application = get_wsgi_application() diff --git a/src/testMultiRootWkspc/workspace5/flaskApp/run.py b/src/testMultiRootWkspc/workspace5/flaskApp/run.py new file mode 100644 index 000000000000..9c3172c3e918 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/flaskApp/run.py @@ -0,0 +1,13 @@ +from flask import Flask, render_template +app = Flask(__name__) + + +@app.route('/') +def hello(): + return render_template('index.html', + value_from_server='this_is_a_value_from_server', + another_value_from_server='this_is_another_value_from_server') + + +if __name__ == '__main__': + app.run() diff --git a/src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html b/src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html new file mode 100644 index 000000000000..6ca5107d23d6 --- /dev/null +++ b/src/testMultiRootWkspc/workspace5/flaskApp/templates/index.html @@ -0,0 +1,9 @@ + + + + +

Hello {{ value_from_server }}!

+

Hello {{ another_value_from_server }}!

+ + + From 0717b8ab7150beccd27b4657e1ec574ca8c16766 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:47:50 -0700 Subject: [PATCH 02/13] add flask and django requirements --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index e7f764089ecf..439a8d6999b7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,5 @@ pytest fabric numba rope +flask +django From 102e4b5f704562971fe1bd202fa3b8ee10537dbb Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:52:08 -0700 Subject: [PATCH 03/13] fix typo --- src/test/debugger/web.framework.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index e4f752678664..b941a560bad0 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -46,7 +46,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { function buildLaunchArgs(workspaceDirectory: string): LaunchRequestArguments { const env = {}; // tslint:disable-next-line:no-string-literal - env['PYTHONPATH'] = path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'experimental', 'ptvsd'); + env['PYTHONPATH'] = '/home/don/Desktop/development/vscode/ptvsd'; // tslint:disable-next-line:no-unnecessary-local-variable const options: LaunchRequestArguments = { From b446c390b875222316cfe0cf1216b7b7567cad75 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:52:49 -0700 Subject: [PATCH 04/13] run only django tests --- src/test/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/index.ts b/src/test/index.ts index 135ca5d8b6c1..464caac75c18 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -13,7 +13,7 @@ process.env.IS_MULTI_ROOT_TEST = IS_MULTI_ROOT_TEST.toString(); // If running on CI server and we're running the debugger tests, then ensure we only run debug tests. // We do this to ensure we only run debugger test, as debugger tests are very flaky on CI. // So the solution is to run them separately and first on CI. -const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : undefined; +const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : 'Django and Flask Debugging'; // You can directly control Mocha options by uncommenting the following lines. // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info. @@ -23,7 +23,7 @@ const options: MochaSetupOptions & { retries: number } = { useColors: true, timeout: 25000, retries: 3, - grep + grep: 'Django and Flask Debugging' }; testRunner.configure(options, { coverageConfig: '../coverconfig.json' }); module.exports = testRunner; From 957ef09e695a759b43c65728e436f34b1ce0a516 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 16:55:23 -0700 Subject: [PATCH 05/13] fix typo --- src/test/debugger/web.framework.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index b941a560bad0..e4f752678664 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -46,7 +46,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { function buildLaunchArgs(workspaceDirectory: string): LaunchRequestArguments { const env = {}; // tslint:disable-next-line:no-string-literal - env['PYTHONPATH'] = '/home/don/Desktop/development/vscode/ptvsd'; + env['PYTHONPATH'] = path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'experimental', 'ptvsd'); // tslint:disable-next-line:no-unnecessary-local-variable const options: LaunchRequestArguments = { From 3a9e297be38026e316d60dc59904aeda02d9e2f4 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:29:30 -0700 Subject: [PATCH 06/13] more logging --- src/test/debugger/web.framework.test.ts | 48 ++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index e4f752678664..2aadbd2d0065 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -3,9 +3,10 @@ 'use strict'; -// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal +// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal no-console import { expect } from 'chai'; +import { spawn } from 'child_process'; import * as fs from 'fs'; import * as getFreePort from 'get-port'; import * as path from 'path'; @@ -133,6 +134,37 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { expect(htmlResult).to.contain('Hello this_is_another_value_from_server'); } + test('Dummy test', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); + const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); + const env = { ...process.env, ...options.env }; + console.log('step1'); + const proc = spawn('python', ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); + console.log('step2'); + proc.stdout.on('data', data => { + console.log(data.toString()); + }); + proc.stderr.on('data', data => { + console.error(data.toString()); + }); + proc.on('error', error => { + console.error(error); + }); + proc.on('close', () => { + console.error('closed'); + }); + proc.on('exit', () => { + console.error('exit'); + }); + console.log('step3'); + await sleep(3000); + console.log('step4'); + const httpResult = await makeHttpRequest(`http://localhost:${port}`); + console.log('step5'); + console.log(httpResult); + console.log('step6'); + }); + test('Test Flask Route and Template debugging', async () => { const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); @@ -142,12 +174,12 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { path.join(workspaceDirectory, 'templates', 'index.html'), 6); }); - test('Test Django Route and Template debugging', async () => { - const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); - const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); + // test('Test Django Route and Template debugging', async () => { + // const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); + // const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); - await testTemplateDebugging(options, port, - path.join(workspaceDirectory, 'home', 'views.py'), 10, - path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); - }); + // await testTemplateDebugging(options, port, + // path.join(workspaceDirectory, 'home', 'views.py'), 10, + // path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); + // }); }); From a426fb987163f1bc288071450e9a5fb8ad918d2b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:33:06 -0700 Subject: [PATCH 07/13] prefix pip with python -m --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fee4079ea762..1eb64ae75600 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,8 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: - - pip install --upgrade -r requirements.txt - - pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ + - python - m pip install --upgrade -r requirements.txt + - python - m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn script: From 8f58935d446b935154f1f740bfc50ebb8367b427 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:37:04 -0700 Subject: [PATCH 08/13] oops --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1eb64ae75600..915c33dd9cad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,8 +36,8 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: - - python - m pip install --upgrade -r requirements.txt - - python - m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ + - python -m pip install --upgrade -r requirements.txt + - python -m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn script: From 0a508a429f7528b97846464dea6a0deb8776256a Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:43:23 -0700 Subject: [PATCH 09/13] more changes --- src/test/debugger/utils.ts | 3 +++ src/test/debugger/web.framework.test.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/debugger/utils.ts b/src/test/debugger/utils.ts index ad59a2fd98e5..adc4a532221a 100644 --- a/src/test/debugger/utils.ts +++ b/src/test/debugger/utils.ts @@ -69,6 +69,9 @@ export async function validateVariablesInFrame(debugClient: DebugClient, export function makeHttpRequest(uri: string): Promise { return new Promise((resolve, reject) => { request.get(uri, (error: any, response: request.Response, body: any) => { + if (error) { + return reject(error); + } if (response.statusCode !== 200) { reject(new Error(`Status code = ${response.statusCode}`)); } else { diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index 2aadbd2d0065..0a9cf4f21065 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -32,7 +32,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { debugClient = await createDebugAdapter(coverageDirectory); }); teardown(async function () { - if (this.currentTest.state !== 'passed') { + if (this.currentTest.state !== 'passed' && fs.existsSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log'))) { console.log(this.currentTest.title); console.log(fs.readFileSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log')).toString()); } From 8de002af43ed1ef2364727797e2bbb9f53ee3388 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 17:51:31 -0700 Subject: [PATCH 10/13] more changes --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 915c33dd9cad..413bca964319 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,9 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: + - which python + - python --version + - python -m pip --version - python -m pip install --upgrade -r requirements.txt - python -m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn From 981d00915dfc1d17e89242a3c05f3bb8ac726330 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 18:04:22 -0700 Subject: [PATCH 11/13] get right python path from test environment --- src/test/common.ts | 11 +++++++++++ src/test/debugger/web.framework.test.ts | 6 +++--- src/test/initialize.ts | 13 +------------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/test/common.ts b/src/test/common.ts index e399012adf2c..5f6d6640e709 100644 --- a/src/test/common.ts +++ b/src/test/common.ts @@ -7,6 +7,8 @@ import { IS_MULTI_ROOT_TEST } from './initialize'; const fileInNonRootWorkspace = path.join(__dirname, '..', '..', 'src', 'test', 'pythonFiles', 'dummy.py'); export const rootWorkspaceUri = getWorkspaceRoot(); +export const PYTHON_PATH = getPythonPath(); + export type PythonSettingKeys = 'workspaceSymbols.enabled' | 'pythonPath' | 'linting.lintOnSave' | 'linting.enabled' | 'linting.pylintEnabled' | @@ -118,3 +120,12 @@ const globalPythonPathSetting = workspace.getConfiguration('python').inspect('py export const clearPythonPathInWorkspaceFolder = async (resource: string | Uri) => retryAsync(setPythonPathInWorkspace)(resource, ConfigurationTarget.WorkspaceFolder); export const setPythonPathInWorkspaceRoot = async (pythonPath: string) => retryAsync(setPythonPathInWorkspace)(undefined, ConfigurationTarget.Workspace, pythonPath); export const resetGlobalPythonPathSetting = async () => retryAsync(restoreGlobalPythonPathSetting)(); + +function getPythonPath(): string { + // tslint:disable-next-line:no-unsafe-any + if (process.env.TRAVIS_PYTHON_PATH && fs.existsSync(process.env.TRAVIS_PYTHON_PATH)) { + // tslint:disable-next-line:no-unsafe-any + return process.env.TRAVIS_PYTHON_PATH; + } + return 'python'; +} diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index 0a9cf4f21065..b31c7fa5ab72 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -14,7 +14,7 @@ import { DebugClient } from 'vscode-debugadapter-testsupport'; import { EXTENSION_ROOT_DIR } from '../../client/common/constants'; import { noop } from '../../client/common/core.utils'; import { DebugOptions, LaunchRequestArguments } from '../../client/debugger/Common/Contracts'; -import { sleep } from '../common'; +import { PYTHON_PATH, sleep } from '../common'; import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize'; import { DEBUGGER_TIMEOUT } from './common/constants'; import { continueDebugging, createDebugAdapter, ExpectedVariable, hitHttpBreakpoint, makeHttpRequest, validateVariablesInFrame } from './utils'; @@ -54,7 +54,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { cwd: workspaceDirectory, program: '', debugOptions: [DebugOptions.RedirectOutput], - pythonPath: 'python', + pythonPath: PYTHON_PATH, args: [], env, envFile: '', @@ -139,7 +139,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); const env = { ...process.env, ...options.env }; console.log('step1'); - const proc = spawn('python', ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); + const proc = spawn(PYTHON_PATH, ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); console.log('step2'); proc.stdout.on('data', data => { console.log(data.toString()); diff --git a/src/test/initialize.ts b/src/test/initialize.ts index 5914d38185e9..f3cba26217bc 100644 --- a/src/test/initialize.ts +++ b/src/test/initialize.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; import { PythonSettings } from '../client/common/configSettings'; import { activated } from '../client/extension'; -import { clearPythonPathInWorkspaceFolder, resetGlobalPythonPathSetting, setPythonPathInWorkspaceRoot } from './common'; +import { clearPythonPathInWorkspaceFolder, PYTHON_PATH, resetGlobalPythonPathSetting, setPythonPathInWorkspaceRoot } from './common'; export * from './constants'; @@ -16,8 +16,6 @@ const workspace3Uri = vscode.Uri.file(path.join(multirootPath, 'workspace3')); //First thing to be executed. process.env['VSC_PYTHON_CI_TEST'] = '1'; -const PYTHON_PATH = getPythonPath(); - // Ability to use custom python environments for testing export async function initializePython() { await resetGlobalPythonPathSetting(); @@ -48,12 +46,3 @@ export async function closeActiveWindows(): Promise { // tslint:disable-next-line:no-unnecessary-callback-wrapper .then(() => resolve(), reject)); } - -function getPythonPath(): string { - // tslint:disable-next-line:no-unsafe-any - if (process.env.TRAVIS_PYTHON_PATH && fs.existsSync(process.env.TRAVIS_PYTHON_PATH)) { - // tslint:disable-next-line:no-unsafe-any - return process.env.TRAVIS_PYTHON_PATH; - } - return 'python'; -} From 1c614e3bc5f9b8b3b691828c62a6c987563fbf1e Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 18:12:37 -0700 Subject: [PATCH 12/13] revert unnecessary changes --- src/test/debugger/web.framework.test.ts | 53 ++++--------------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/src/test/debugger/web.framework.test.ts b/src/test/debugger/web.framework.test.ts index b31c7fa5ab72..ca3ca6c6a19f 100644 --- a/src/test/debugger/web.framework.test.ts +++ b/src/test/debugger/web.framework.test.ts @@ -6,8 +6,6 @@ // tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-http-string no-string-literal no-console import { expect } from 'chai'; -import { spawn } from 'child_process'; -import * as fs from 'fs'; import * as getFreePort from 'get-port'; import * as path from 'path'; import { DebugClient } from 'vscode-debugadapter-testsupport'; @@ -31,11 +29,7 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { const coverageDirectory = path.join(EXTENSION_ROOT_DIR, `debug_coverage_django_flask${testCounter += 1}`); debugClient = await createDebugAdapter(coverageDirectory); }); - teardown(async function () { - if (this.currentTest.state !== 'passed' && fs.existsSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log'))) { - console.log(this.currentTest.title); - console.log(fs.readFileSync(path.join(EXTENSION_ROOT_DIR, 'experimental_debug.log')).toString()); - } + teardown(async () => { // Wait for a second before starting another test (sometimes, sockets take a while to get closed). await sleep(1000); try { @@ -134,37 +128,6 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { expect(htmlResult).to.contain('Hello this_is_another_value_from_server'); } - test('Dummy test', async () => { - const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); - const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); - const env = { ...process.env, ...options.env }; - console.log('step1'); - const proc = spawn(PYTHON_PATH, ['-m', 'flask', ...options.args], { cwd: workspaceDirectory, env }); - console.log('step2'); - proc.stdout.on('data', data => { - console.log(data.toString()); - }); - proc.stderr.on('data', data => { - console.error(data.toString()); - }); - proc.on('error', error => { - console.error(error); - }); - proc.on('close', () => { - console.error('closed'); - }); - proc.on('exit', () => { - console.error('exit'); - }); - console.log('step3'); - await sleep(3000); - console.log('step4'); - const httpResult = await makeHttpRequest(`http://localhost:${port}`); - console.log('step5'); - console.log(httpResult); - console.log('step6'); - }); - test('Test Flask Route and Template debugging', async () => { const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'flaskApp'); const { options, port } = await buildFlaskLaunchArgs(workspaceDirectory); @@ -174,12 +137,12 @@ suite(`Django and Flask Debugging: ${debuggerType}`, () => { path.join(workspaceDirectory, 'templates', 'index.html'), 6); }); - // test('Test Django Route and Template debugging', async () => { - // const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); - // const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); + test('Test Django Route and Template debugging', async () => { + const workspaceDirectory = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'djangoApp'); + const { options, port } = await buildDjangoLaunchArgs(workspaceDirectory); - // await testTemplateDebugging(options, port, - // path.join(workspaceDirectory, 'home', 'views.py'), 10, - // path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); - // }); + await testTemplateDebugging(options, port, + path.join(workspaceDirectory, 'home', 'views.py'), 10, + path.join(workspaceDirectory, 'home', 'templates', 'index.html'), 6); + }); }); From 4ab004cf1e73cf5490c294866c050d44e9771359 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 5 Apr 2018 19:02:19 -0700 Subject: [PATCH 13/13] revert unnecessary changes --- .travis.yml | 3 --- src/test/index.ts | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 413bca964319..915c33dd9cad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,9 +36,6 @@ before_install: | yarn global add azure-cli export TRAVIS_PYTHON_PATH=`which python` install: - - which python - - python --version - - python -m pip --version - python -m pip install --upgrade -r requirements.txt - python -m pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/ - yarn diff --git a/src/test/index.ts b/src/test/index.ts index 464caac75c18..135ca5d8b6c1 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -13,7 +13,7 @@ process.env.IS_MULTI_ROOT_TEST = IS_MULTI_ROOT_TEST.toString(); // If running on CI server and we're running the debugger tests, then ensure we only run debug tests. // We do this to ensure we only run debugger test, as debugger tests are very flaky on CI. // So the solution is to run them separately and first on CI. -const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : 'Django and Flask Debugging'; +const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : undefined; // You can directly control Mocha options by uncommenting the following lines. // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info. @@ -23,7 +23,7 @@ const options: MochaSetupOptions & { retries: number } = { useColors: true, timeout: 25000, retries: 3, - grep: 'Django and Flask Debugging' + grep }; testRunner.configure(options, { coverageConfig: '../coverconfig.json' }); module.exports = testRunner;