public async Task create_template_function_dotnet_space_name() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime dotnet", "new --template \"http trigger\" --name testfunc2" }, OutputContains = new[] { "The function \"testfunc2\" was created successfully from the \"http trigger\" template." } }, _output); }
public async Task create_template_function_using_alias() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "new --language js --template \"http trigger\" --name testfunc" }, OutputContains = new[] { "The function \"testfunc\" was created successfully from the \"http trigger\" template." } }, _output); }
public async Task create_function_custom() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime custom --no-bundle", "new --template \"Http Trigger\" --name testfunc" }, OutputContains = new[] { "The function \"testfunc\" was created successfully from the \"Http Trigger\" template." } }, _output); }
public Task init_docker_only_no_project() { return(CliTester.Run(new RunConfiguration { Commands = new[] { $"init . --docker-only" }, HasStandardError = true, ErrorContains = new[] { $"Unable to find project root" } }, _output)); }
public Task init_managed_dependencies_is_only_supported_in_powershell() { return(CliTester.Run(new RunConfiguration { Commands = new[] { $"init . --worker-runtime python --managed-dependencies " }, HasStandardError = true, ErrorContains = new[] { $"Managed dependencies is only supported for PowerShell" } }, _output)); }
public async Task create_httpTrigger_with_authConfigured_dotnet() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime dotnet", "new --template HttpTrigger --name testfunc --authlevel function" }, OutputContains = new[] { "The function \"testfunc\" was created successfully from the \"HttpTrigger\" template." } }, _output); }
public async Task create_httpTrigger_Invalid_AuthConfig_returns_error() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "new --template httpTrigger --name testfunc --authlevel invalid" }, OutputContains = new[] { "Authorization level is applicable to templates that use Http trigger, Allowed values: [function, anonymous, admin]. Authorization level is not enforced when running functions from core tools" } }, _output); }
public async Task ListFunctionsWorks() { TestConditions.SkipIfAzureServicePrincipalNotDefined(); Environment.SetEnvironmentVariable("CLI_DEBUG", "0"); try { await CliTester.Run(new[] { new RunConfiguration { Commands = new[] { "azure functionapp list-functions core-tools-list-functions", }, OutputContains = new string[] { "api/httpwithkey", "api/httpwithoutkey" }, OutputDoesntContain = new string[] { "api/httpwithkey?code=", "api/httpwithoutkey?code=" } }, new RunConfiguration { Commands = new [] { "azure functionapp list-functions core-tools-list-functions --show-keys" }, OutputContains = new string [] { "api/httpwithkey?code=", "api/httpwithoutkey" }, OutputDoesntContain = new string[] { "api/httpwithoutkey?code=" } } }); } finally { Environment.SetEnvironmentVariable("CLI_DEBUG", "1"); } }
public async Task create_timerTrigger_authConfigured_returns_error() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "new --template TimerTrigger --name testfunc --authlevel function" }, HasStandardError = true, ErrorContains = new[] { Constants.AuthLevelErrorMessage } }, _output); }
public Task bundlesconfiguredbydefault_no_action() { return(CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "new --template SendGrid --name testfunc", "extensions install" }, OutputContains = new[] { "No action performed" }, CommandTimeout = TimeSpan.FromMinutes(1) }, _output)); }
public Task init_with_Dockerfile(string workerRuntime) { return(CliTester.Run(new RunConfiguration { Commands = new[] { $"init . --worker-runtime {workerRuntime} --docker" }, CheckFiles = new[] { new FileResult { Name = "Dockerfile", ContentContains = new[] { $"FROM mcr.microsoft.com/azure-functions/{workerRuntime}:2.0" } } }, OutputContains = new[] { "Dockerfile" } }, _output)); }
public Task init_with_Dockerfile_for_csx() { return(CliTester.Run(new RunConfiguration { Commands = new[] { $"init . --worker-runtime dotnet --docker --csx" }, CheckFiles = new[] { new FileResult { Name = "Dockerfile", ContentNotContains = new[] { "dotnet publish" }, ContentContains = new[] { $"FROM mcr.microsoft.com/azure-functions/dotnet:2.0" } } }, OutputContains = new[] { "Dockerfile" } }, _output)); }
public async Task start_loglevel_overrriden_in_host_json_category_filter() { var functionName = "HttpTriggerCSharp"; await CliTester.Run(new RunConfiguration[] { new RunConfiguration { Commands = new[] { "init . --worker-runtime dotnet", $"new --template Httptrigger --name {functionName}", }, Test = async(workingDir, p) => { var filePath = Path.Combine(workingDir, "host.json"); string hostJsonContent = "{\"version\": \"2.0\",\"logging\": {\"logLevel\": {\"Default\": \"None\", \"Host.Startup\": \"Information\"}}}"; await File.WriteAllTextAsync(filePath, hostJsonContent); }, }, new RunConfiguration { Commands = new[] { "start" }, ExpectExit = false, OutputContains = new [] { "Found the following functions:" }, OutputDoesntContain = new string[] { "Reading host configuration file" }, Test = async(_, p) => { // give the host time to load functions and print any errors await Task.Delay(TimeSpan.FromSeconds(10)); p.Kill(); } }, }, _output, startHost : true); }
public async Task DurableRaiseEventTest_FileInput() { Skip.If(string.IsNullOrEmpty(StorageConnectionString), reason: _storageReason); string taskHubName = "raiseEventFileInputTest"; DurableHelper.SetTaskHubName(WorkingDirPath, taskHubName); Environment.SetEnvironmentVariable(DurableManager.DefaultConnectionStringKey, StorageConnectionString); string filename = Path.Combine(WorkingDirPath, "raiseEvent.json"); var testObject = new { Name = "RaiseEvent", Hello = "World" }; File.WriteAllText(filename, JsonConvert.SerializeObject(testObject)); string instanceId = $"{Guid.NewGuid():N}"; await CliTester.Run(new RunConfiguration { Commands = new[] { $"durable start-new --function-name JsonInput --id {instanceId} --task-hub-name {taskHubName}", $"durable raise-event --id {instanceId} --event-name operation --event-data @raiseEvent.json --task-hub-name {taskHubName}", $"durable get-runtime-status --id {instanceId}" }, OutputContains = new string[] { $"Raised event 'operation' to instance '{instanceId}'", "\"OrchestrationStatus\": 0", } }, _output, workingDir : WorkingDirPath, startHost : true); Environment.SetEnvironmentVariable(DurableManager.DefaultConnectionStringKey, null); File.Delete(filename); }
public async Task DurableStartNewTest_FileInput() { Skip.If(true, reason: "This test fails intermittently, needs to be fixed"); Skip.If(string.IsNullOrEmpty(StorageConnectionString), reason: _storageReason); string taskHubName = "startNewFileInputTest"; DurableHelper.SetTaskHubName(WorkingDirPath, taskHubName); Environment.SetEnvironmentVariable(DurableManager.DefaultConnectionStringKey, StorageConnectionString); string filename = Path.Combine(WorkingDirPath, "startnew.json"); var testObject = new { Name = "StartNew", Hello = "World" }; File.WriteAllText(filename, JsonConvert.SerializeObject(testObject)); string instanceId = $"{Guid.NewGuid():N}"; await CliTester.Run(new RunConfiguration { Commands = new[] { $"durable start-new --function-name JsonInput --input @startnew.json --task-hub-name {taskHubName} --id {instanceId}", $"durable get-runtime-status --id {instanceId}" }, OutputContains = new string[] { "Started 'JsonInput'", "\"OrchestrationStatus\": 0", } }, _output, workingDir : WorkingDirPath, startHost : true); Environment.SetEnvironmentVariable(DurableManager.DefaultConnectionStringKey, null); File.Delete(filename); }
public async void RemoteBuildPythonFunctionApp() { TestConditions.SkipIfEnableDeploymentTestsNotDefined(); await CliTester.Run(new[] { new RunConfiguration { Commands = new[] { "init . --worker-runtime python", "new -l python -t HttpTrigger -n httptrigger", $"azure functionapp publish {linuxConsumptionPythonFunctionApp} --build remote" }, OutputContains = new string[] { "Remote build succeeded!" }, CommandTimeout = TimeSpan.FromMinutes(5) }, }, _output); }
public async Task init_with_python_Dockerfile() { WorkerLanguageVersionInfo worker = await PythonHelpers.GetEnvironmentPythonVersion(); Skip.If(worker == null); await CliTester.Run(new RunConfiguration { Commands = new[] { $"init . --worker-runtime python --docker" }, CheckFiles = new[] { new FileResult { Name = "Dockerfile", ContentContains = new[] { $"FROM mcr.microsoft.com/azure-functions/python:2.0-python{worker.Major}.{worker.Minor}" } } }, OutputContains = new[] { "Dockerfile" } }, _output); }
public async Task start_displays_error_on_invalid_function_json() { var functionName = "HttpTriggerJS"; await CliTester.Run(new RunConfiguration[] { new RunConfiguration { Commands = new[] { "init . --worker-runtime node", $"new --template \"Http Trigger\" --name {functionName}", }, Test = async(workingDir, _) => { var filePath = Path.Combine(workingDir, functionName, "function.json"); var functionJson = await File.ReadAllTextAsync(filePath); functionJson = functionJson.Replace("\"type\": \"http\"", "\"type\": \"http2\""); await File.WriteAllTextAsync(filePath, functionJson); } }, new RunConfiguration { Commands = new[] { "start" }, ExpectExit = false, OutputContains = new [] { "The binding type(s) 'http2' are not registered. Please ensure the type is correct and the binding extension is installed." }, Test = async(_, p) => { // give the host time to load functions and print any errors await Task.Delay(TimeSpan.FromSeconds(10)); p.Kill(); } } }, _output); }
public async Task start_nodejs_with_inspect() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "new --template \"Http trigger\" --name HttpTrigger", "start --language-worker -- \"--inspect=5050\"" }, ExpectExit = false, OutputContains = new[] { "Debugger listening on ws://127.0.0.1:5050" }, Test = async(_, p) => { await Task.Delay(TimeSpan.FromSeconds(15)); p.Kill(); }, }, _output); }
public Task init_with_worker_runtime(string workerRuntime) { var files = new List <FileResult> { new FileResult { Name = "local.settings.json", ContentContains = new [] { "FUNCTIONS_WORKER_RUNTIME", workerRuntime } }, }; if (workerRuntime == "powershell") { files.Add(new FileResult { Name = "profile.ps1", ContentContains = new[] { "# Azure Functions profile.ps1" } }); } return(CliTester.Run(new RunConfiguration { Commands = new[] { $"init . --worker-runtime {workerRuntime}" }, CheckFiles = files.ToArray(), OutputContains = new[] { "Writing .gitignore", "Writing host.json", "Writing local.settings.json", $".vscode{Path.DirectorySeparatorChar}extensions.json", }, OutputDoesntContain = new[] { "Initialized empty Git repository" } }, _output)); }
public Task init_python_app_twice() { return(CliTester.Run(new RunConfiguration { Commands = new[] { "init \"anapp\" --worker-runtime python", "init \"anapp\" --worker-runtime python" }, OutputContains = new[] { "Writing .gitignore", "Writing host.json", "Writing local.settings.json", $".vscode{Path.DirectorySeparatorChar}extensions.json", "requirements.txt already exists. Skipped!", ".gitignore already exists. Skipped!", "host.json already exists. Skipped!", "local.settings.json already exists. Skipped!", $".vscode{Path.DirectorySeparatorChar}extensions.json already exists. Skipped!" } }, _output)); }
public async Task start_nodejs_loglevel_overrriden_in_settings() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "settings add AzureFunctionsJobHost__logging__logLevel__Default Debug", "new --template \"Http trigger\" --name HttpTrigger", "start" }, ExpectExit = false, OutputContains = new[] { "Worker path for language worker node" }, Test = async(_, p) => { await Task.Delay(TimeSpan.FromSeconds(15)); p.Kill(); }, }, _output); }
public async Task create_template_function_sanitization_dotnet() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init 12n.ew-file$ --worker-runtime dotnet", "new --prefix 12n.ew-file$ --template HttpTrigger --name [email protected]$" }, CheckFiles = new[] { new FileResult { Name = "12n.ew-file$/_12_n_other_file_.cs", ContentContains = new[] { "namespace _12n.ew_file_", "public static class _12_n_other_file_" } } } }, _output); }
public async Task add_setting_plain_text() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "settings add testKey valueValue" }, CheckFiles = new[] { new FileResult { Name = "local.settings.json", ContentContains = new[] { "\"IsEncrypted\": false", "\"testKey\": \"valueValue\"" } } } }, _output); }
public Task init_function_app_powershell_supports_managed_dependencies() { return(CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime powershell --managed-dependencies" }, CheckFiles = new FileResult[] { new FileResult { Name = "host.json", ContentContains = new [] { "managedDependency", "enabled", "true" } }, new FileResult { Name = "requirements.psd1", ContentContains = new [] { "Az", } } }, OutputContains = new[] { "Writing profile.ps1", "Writing requirements.psd1", "Writing .gitignore", "Writing host.json", "Writing local.settings.json", $".vscode{Path.DirectorySeparatorChar}extensions.json", } }, _output)); }
public async Task start_nodejs() { await CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node", "new --template \"Http trigger\" --name HttpTrigger", "start" }, ExpectExit = false, OutputContains = new[] { "Functions:", "HttpTrigger: [GET,POST] http://localhost:7071/api/HttpTrigger" }, OutputDoesntContain = new string[] { "Initializing function HTTP routes", "Content root path:" // ASPNETCORE_SUPPRESSSTATUSMESSAGES is set to true by default }, Test = async(workingDir, p) => { using (var client = new HttpClient() { BaseAddress = new Uri("http://localhost:7071/") }) { (await WaitUntilReady(client)).Should().BeTrue(because: _serverNotReady); var response = await client.GetAsync("/api/HttpTrigger?name=Test"); var result = await response.Content.ReadAsStringAsync(); p.Kill(); result.Should().Be("Hello, Test. This HTTP triggered function executed successfully.", because: "response from default function should be 'Hello, {name}. This HTTP triggered function executed successfully.'"); } }, }, _output); }
public async Task Create_TOTP_Record_and_Generate_Code() { using var cli = new CliTester(); await cli.InitAsync(); await cli.InvokeSuccessfullyAsync("reg", "--email", "*****@*****.**", "--password", "foobar", "--raw-session"); var sessionKey = cli.ReadOut(); cli.SetEnv("KYPR_SESSION", sessionKey); await cli.InvokeSuccessfullyAsync("new", "vault", "--label", "v1"); _ = cli.ReadOut(); await cli.InvokeSuccessfullyAsync("new", "rec", "--vault", "v1", "--file", "samples/record-totp1.json"); var recId = cli.ReadOut().Trim(); await cli.InvokeSuccessfullyAsync("get", "otp", "--record", recId); var otpCode = cli.ReadOut().Trim(); Assert.NotEmpty(otpCode); Assert.Equal(6, otpCode.Length); var otpSecret = "I65VU7K5ZQL7WB4E"; var otpCodeUrl = $"https://authenticationtest.com/totp/?secret={otpSecret}"; using var http = new HttpClient(); var otpJson = await http.GetStringAsync(otpCodeUrl); var otpResp = JsonSerializer.Deserialize <AuthTestOtpResponse>(otpJson); Assert.Equal(otpResp !.code, otpCode); }
public Task try_install_with_a_version() { return(CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime node --no-bundle", "new --template SendGrid --name testfunc", "extensions install", "extensions install -p Microsoft.Azure.WebJobs.Extensions.Storage -v 3.0.8" }, OutputContains = new[] { "Restoring packages for", "Restore completed" }, OutputDoesntContain = new[] { "No action performed because no functions in your app require extensions" }, CheckFiles = new[] { new FileResult { Name = "extensions.csproj", Exists = true, ContentContains = new[] { "Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator", "Microsoft.Azure.WebJobs.Extensions.SendGrid", "Include=\"Microsoft.Azure.WebJobs.Extensions.Storage\" Version=\"3.0.8\"" } } }, CommandTimeout = TimeSpan.FromMinutes(1) }, _output)); }
public Task pack_python_from_cache() { var syncDirMessage = "Directory .python_packages already in sync with requirements.txt. Skipping restoring dependencies..."; return(CliTester.Run(new[] { // Create a Python function new RunConfiguration { Commands = new[] { "init . --worker-runtime python", "new --template \"Httptrigger\" --name httptrigger", }, CheckFiles = new FileResult[] { new FileResult { Name = "local.settings.json", ContentContains = new [] { "FUNCTIONS_WORKER_RUNTIME", "python" } } }, OutputContains = new[] { "Writing .gitignore", "Writing host.json", "Writing local.settings.json" } }, // Make sure pack works new RunConfiguration { Commands = new[] { "pack", }, OutputContains = new[] { "Creating a new package" }, CheckFiles = new FileResult[] { new FileResult { Name = Path.Combine(".python_packages", "requirements.txt.md5") } }, OutputDoesntContain = new[] { syncDirMessage }, CommandTimeout = TimeSpan.FromMinutes(2) }, // Without changing requirements.txt, make sure pack does not restore again new RunConfiguration { Commands = new[] { "pack", }, OutputContains = new[] { "Creating a new package", syncDirMessage }, CheckFiles = new FileResult[] { new FileResult { Name = Path.Combine(".python_packages", "requirements.txt.md5") } }, CommandTimeout = TimeSpan.FromMinutes(2) }, // Update requirements.txt and make sure pack restores the dependencies new RunConfiguration { PreTest = (workingDir) => { var reqTxt = Path.Combine(workingDir, "requirements.txt"); _output.WriteLine($"Writing to file {reqTxt}"); FileSystemHelpers.WriteAllTextToFile(reqTxt, "requests"); }, Commands = new[] { "pack", }, OutputContains = new[] { "Creating a new package" }, CheckFiles = new FileResult[] { new FileResult { Name = Path.Combine(".python_packages", "requirements.txt.md5") } }, OutputDoesntContain = new[] { syncDirMessage }, CommandTimeout = TimeSpan.FromMinutes(2) } }, _output)); }
public Task init_function_app_powershell_enable_managed_dependencies_and_set_default_version() { return(CliTester.Run(new RunConfiguration { Commands = new[] { "init . --worker-runtime powershell --managed-dependencies" }, CheckFiles = new FileResult[] { new FileResult { Name = "host.json", ContentContains = new [] { "logging", "applicationInsights", "extensionBundle", "managedDependency", "enabled", "true" } }, new FileResult { Name = "requirements.psd1", ContentContains = new [] { "Az", } }, new FileResult { Name = "profile.ps1", ContentContains = new [] { "env:MSI_SECRET", "Disable-AzContextAutosave", "Connect-AzAccount -Identity" } }, new FileResult { Name = "local.settings.json", ContentContains = new [] { "FUNCTIONS_WORKER_RUNTIME", "powershell", "FUNCTIONS_WORKER_RUNTIME_VERSION", "~6" } } }, OutputContains = new[] { "Writing profile.ps1", "Writing requirements.psd1", "Writing .gitignore", "Writing host.json", "Writing local.settings.json", $".vscode{Path.DirectorySeparatorChar}extensions.json", } }, _output)); }