diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index 9b491337a970..6c4e6adbcde6 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -674,9 +674,9 @@ stages: # Build the shared framework - script: ./build.cmd -ci -all -pack -arch x64 -buildNative /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log /bl:artifacts/log/helix.build.x64.binlog displayName: Build shared fx - - script: .\restore.cmd -ci + - script: .\restore.cmd -ci /p:BuildInteropProjects=true displayName: Restore - - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl + - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildInteropProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl displayName: Run build.cmd helix target env: HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues @@ -701,7 +701,7 @@ stages: # Build the x86 shared framework - script: .\restore.cmd -ci displayName: Restore - - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:BuildAllProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl + - script: .\build.cmd -ci -NoRestore -test -projects eng\helix\helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:BuildAllProjects=true /p:BuildInteropProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl displayName: Run build.cmd helix target env: HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues diff --git a/.azure/pipelines/quarantined-tests.yml b/.azure/pipelines/quarantined-tests.yml index 415853ed8e18..791283efd6f9 100644 --- a/.azure/pipelines/quarantined-tests.yml +++ b/.azure/pipelines/quarantined-tests.yml @@ -35,7 +35,7 @@ jobs: displayName: Build shared fx - script: .\restore.cmd -ci displayName: Restore - - script: .\build.cmd -ci -NoRestore -test -noBuildJava -projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl + - script: .\build.cmd -ci -NoRestore -test -noBuildJava -projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true /p:BuildAllProjects=true /p:BuildInteropProjects=true /p:BuildNative=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log -bl displayName: Run build.cmd helix target env: HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues diff --git a/Directory.Build.targets b/Directory.Build.targets index a62e3ed6a48b..9a30afbb8e09 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -167,5 +167,7 @@ + + diff --git a/eng/Build.props b/eng/Build.props index 4c0542db15da..6f1b3f190898 100644 --- a/eng/Build.props +++ b/eng/Build.props @@ -123,6 +123,13 @@ + + + + + + + + + + $(RestoreAdditionalProjectSources);$(ArtifactsShippingPackagesDir) + $(TargetingPackVersion) + $(AspNetCoreBaselineVersion) + + + + + + + diff --git a/src/Grpc/test/testassets/InteropWebsite/InteropWebsite.csproj b/src/Grpc/test/testassets/InteropWebsite/InteropWebsite.csproj new file mode 100644 index 000000000000..4b8d6d38509f --- /dev/null +++ b/src/Grpc/test/testassets/InteropWebsite/InteropWebsite.csproj @@ -0,0 +1,19 @@ + + + + $(DefaultNetCoreTargetFramework) + InProcess + false + enable + 8.0 + + + + + + + + + + + diff --git a/src/Grpc/test/testassets/InteropWebsite/Program.cs b/src/Grpc/test/testassets/InteropWebsite/Program.cs new file mode 100644 index 000000000000..fffaf75c559e --- /dev/null +++ b/src/Grpc/test/testassets/InteropWebsite/Program.cs @@ -0,0 +1,63 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using System.IO; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; + +namespace InteropTestsWebsite +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.ConfigureKestrel((context, options) => + { + // Support --port and --use_tls cmdline arguments normally supported + // by gRPC interop servers. + var useTls = context.Configuration.GetValue("use_tls", false); + + options.Limits.MinRequestBodyDataRate = null; + options.ListenAnyIP(0, listenOptions => + { + Console.WriteLine($"Enabling connection encryption: {useTls}"); + + if (useTls) + { + var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location); + var certPath = Path.Combine(basePath!, "Certs", "server1.pfx"); + + listenOptions.UseHttps(certPath, "1111"); + } + listenOptions.Protocols = HttpProtocols.Http2; + }); + }); + webBuilder.UseStartup(); + }); + } +} diff --git a/src/Grpc/test/testassets/InteropWebsite/Startup.cs b/src/Grpc/test/testassets/InteropWebsite/Startup.cs new file mode 100644 index 000000000000..4715d1fbbca4 --- /dev/null +++ b/src/Grpc/test/testassets/InteropWebsite/Startup.cs @@ -0,0 +1,49 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using Grpc.Testing; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace InteropTestsWebsite +{ + public class Startup + { + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + services.AddGrpc(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostApplicationLifetime applicationLifetime) + { + // Required to notify test infrastructure that it can begin tests + applicationLifetime.ApplicationStarted.Register(() => Console.WriteLine("Application started.")); + + app.UseRouting(); + app.UseEndpoints(endpoints => + { + endpoints.MapGrpcService(); + }); + } + } +} diff --git a/src/Grpc/test/testassets/InteropWebsite/TestServiceImpl.cs b/src/Grpc/test/testassets/InteropWebsite/TestServiceImpl.cs new file mode 100644 index 000000000000..918500cd2562 --- /dev/null +++ b/src/Grpc/test/testassets/InteropWebsite/TestServiceImpl.cs @@ -0,0 +1,149 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using System.Linq; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using InteropTestsWebsite; + +namespace Grpc.Testing +{ + // Implementation copied from https://github.com/grpc/grpc/blob/master/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs + public class TestServiceImpl : TestService.TestServiceBase + { + public override Task EmptyCall(Empty request, ServerCallContext context) + { + return Task.FromResult(new Empty()); + } + + public override async Task UnaryCall(SimpleRequest request, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context, request.ResponseCompressed?.Value ?? false); + EnsureEchoStatus(request.ResponseStatus, context); + EnsureCompression(request.ExpectCompressed, context); + + var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; + return response; + } + + public override async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context, request.ResponseParameters.Any(rp => rp.Compressed?.Value ?? false)); + EnsureEchoStatus(request.ResponseStatus, context); + + foreach (var responseParam in request.ResponseParameters) + { + responseStream.WriteOptions = !(responseParam.Compressed?.Value ?? false) + ? new WriteOptions(WriteFlags.NoCompress) + : null; + + var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; + await responseStream.WriteAsync(response); + } + } + + public override async Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context); + + int sum = 0; + await requestStream.ForEachAsync(request => + { + EnsureCompression(request.ExpectCompressed, context); + + sum += request.Payload.Body.Length; + return Task.CompletedTask; + }); + return new StreamingInputCallResponse { AggregatedPayloadSize = sum }; + } + + public override async Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context); + + await requestStream.ForEachAsync(async request => + { + EnsureEchoStatus(request.ResponseStatus, context); + foreach (var responseParam in request.ResponseParameters) + { + var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; + await responseStream.WriteAsync(response); + } + }); + } + + public override Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + throw new NotImplementedException(); + } + + private static Payload CreateZerosPayload(int size) + { + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; + } + + private static async Task EnsureEchoMetadataAsync(ServerCallContext context, bool enableCompression = false) + { + var echoInitialList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-initial").ToList(); + + // Append grpc internal compression header if compression is requested by the client + if (enableCompression) + { + echoInitialList.Add(new Metadata.Entry("grpc-internal-encoding-request", "gzip")); + } + + if (echoInitialList.Any()) { + var entry = echoInitialList.Single(); + await context.WriteResponseHeadersAsync(new Metadata { entry }); + } + + var echoTrailingList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ToList(); + if (echoTrailingList.Any()) { + context.ResponseTrailers.Add(echoTrailingList.Single()); + } + } + + private static void EnsureEchoStatus(EchoStatus responseStatus, ServerCallContext context) + { + if (responseStatus != null) + { + var statusCode = (StatusCode)responseStatus.Code; + context.Status = new Status(statusCode, responseStatus.Message); + } + } + + private static void EnsureCompression(BoolValue? expectCompressed, ServerCallContext context) + { + if (expectCompressed != null) + { + // ServerCallContext.RequestHeaders filters out grpc-* headers + // Get grpc-encoding from HttpContext instead + var encoding = context.GetHttpContext().Request.Headers.SingleOrDefault(h => h.Key == "grpc-encoding").Value.SingleOrDefault(); + if (expectCompressed.Value) + { + if (encoding == null || encoding == "identity") + { + throw new RpcException(new Status(StatusCode.InvalidArgument, string.Empty)); + } + } + } + } + } +} diff --git a/src/Grpc/test/testassets/Proto/grpc/testing/empty.proto b/src/Grpc/test/testassets/Proto/grpc/testing/empty.proto new file mode 100644 index 000000000000..6a0aa88dfde1 --- /dev/null +++ b/src/Grpc/test/testassets/Proto/grpc/testing/empty.proto @@ -0,0 +1,28 @@ + +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package grpc.testing; + +// An empty message that you can re-use to avoid defining duplicated empty +// messages in your project. A typical example is to use it as argument or the +// return value of a service API. For instance: +// +// service Foo { +// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; +// }; +// +message Empty {} diff --git a/src/Grpc/test/testassets/Proto/grpc/testing/messages.proto b/src/Grpc/test/testassets/Proto/grpc/testing/messages.proto new file mode 100644 index 000000000000..7b1b7286dced --- /dev/null +++ b/src/Grpc/test/testassets/Proto/grpc/testing/messages.proto @@ -0,0 +1,165 @@ + +// Copyright 2015-2016 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Message definitions to be used by integration test service definitions. + +syntax = "proto3"; + +package grpc.testing; + +// TODO(dgq): Go back to using well-known types once +// https://github.com/grpc/grpc/issues/6980 has been fixed. +// import "google/protobuf/wrappers.proto"; +message BoolValue { + // The bool value. + bool value = 1; +} + +// The type of payload that should be returned. +enum PayloadType { + // Compressable text format. + COMPRESSABLE = 0; +} + +// A block of data, to simply increase gRPC message size. +message Payload { + // The type of data in body. + PayloadType type = 1; + // Primary contents of payload. + bytes body = 2; +} + +// A protobuf representation for grpc status. This is used by test +// clients to specify a status that the server should attempt to return. +message EchoStatus { + int32 code = 1; + string message = 2; +} + +// Unary request. +message SimpleRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, server randomly chooses one from other formats. + PayloadType response_type = 1; + + // Desired payload size in the response from the server. + int32 response_size = 2; + + // Optional input payload sent along with the request. + Payload payload = 3; + + // Whether SimpleResponse should include username. + bool fill_username = 4; + + // Whether SimpleResponse should include OAuth scope. + bool fill_oauth_scope = 5; + + // Whether to request the server to compress the response. This field is + // "nullable" in order to interoperate seamlessly with clients not able to + // implement the full compression tests by introspecting the call to verify + // the response's compression status. + BoolValue response_compressed = 6; + + // Whether server should return a given status + EchoStatus response_status = 7; + + // Whether the server should expect this request to be compressed. + BoolValue expect_compressed = 8; +} + +// Unary response, as configured by the request. +message SimpleResponse { + // Payload to increase message size. + Payload payload = 1; + // The user the request came from, for verifying authentication was + // successful when the client expected it. + string username = 2; + // OAuth scope. + string oauth_scope = 3; +} + +// Client-streaming request. +message StreamingInputCallRequest { + // Optional input payload sent along with the request. + Payload payload = 1; + + // Whether the server should expect this request to be compressed. This field + // is "nullable" in order to interoperate seamlessly with servers not able to + // implement the full compression tests by introspecting the call to verify + // the request's compression status. + BoolValue expect_compressed = 2; + + // Not expecting any payload from the response. +} + +// Client-streaming response. +message StreamingInputCallResponse { + // Aggregated size of payloads received from the client. + int32 aggregated_payload_size = 1; +} + +// Configuration for a particular response. +message ResponseParameters { + // Desired payload sizes in responses from the server. + int32 size = 1; + + // Desired interval between consecutive responses in the response stream in + // microseconds. + int32 interval_us = 2; + + // Whether to request the server to compress the response. This field is + // "nullable" in order to interoperate seamlessly with clients not able to + // implement the full compression tests by introspecting the call to verify + // the response's compression status. + BoolValue compressed = 3; +} + +// Server-streaming request. +message StreamingOutputCallRequest { + // Desired payload type in the response from the server. + // If response_type is RANDOM, the payload from each response in the stream + // might be of different types. This is to simulate a mixed type of payload + // stream. + PayloadType response_type = 1; + + // Configuration for each expected response message. + repeated ResponseParameters response_parameters = 2; + + // Optional input payload sent along with the request. + Payload payload = 3; + + // Whether server should return a given status + EchoStatus response_status = 7; +} + +// Server-streaming response, as configured by the request and parameters. +message StreamingOutputCallResponse { + // Payload to increase response size. + Payload payload = 1; +} + +// For reconnect interop test only. +// Client tells server what reconnection parameters it used. +message ReconnectParams { + int32 max_reconnect_backoff_ms = 1; +} + +// For reconnect interop test only. +// Server tells client whether its reconnects are following the spec and the +// reconnect backoffs it saw. +message ReconnectInfo { + bool passed = 1; + repeated int32 backoff_ms = 2; +} diff --git a/src/Grpc/test/testassets/Proto/grpc/testing/test.proto b/src/Grpc/test/testassets/Proto/grpc/testing/test.proto new file mode 100644 index 000000000000..86d6ab60506a --- /dev/null +++ b/src/Grpc/test/testassets/Proto/grpc/testing/test.proto @@ -0,0 +1,79 @@ + +// Copyright 2015-2016 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. + +syntax = "proto3"; + +import "empty.proto"; +import "messages.proto"; + +package grpc.testing; + +// A simple service to test the various types of RPCs and experiment with +// performance with various types of payload. +service TestService { + // One empty request followed by one empty response. + rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); + + // One request followed by one response. + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // One request followed by one response. Response has cache control + // headers set such that a caching HTTP proxy (such as GFE) can + // satisfy subsequent requests. + rpc CacheableUnaryCall(SimpleRequest) returns (SimpleResponse); + + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + rpc StreamingOutputCall(StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + rpc StreamingInputCall(stream StreamingInputCallRequest) + returns (StreamingInputCallResponse); + + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + rpc FullDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + rpc HalfDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // The test server will not implement this method. It will be used + // to test the behavior when clients call unimplemented methods. + rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty); +} + +// A simple service NOT implemented at servers so clients can test for +// that case. +service UnimplementedService { + // A call that no server should implement + rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty); +} + +// A service used to control reconnect server. +service ReconnectService { + rpc Start(grpc.testing.ReconnectParams) returns (grpc.testing.Empty); + rpc Stop(grpc.testing.Empty) returns (grpc.testing.ReconnectInfo); +} diff --git a/src/Grpc/test/testassets/README.md b/src/Grpc/test/testassets/README.md new file mode 100644 index 000000000000..d7798c92695d --- /dev/null +++ b/src/Grpc/test/testassets/README.md @@ -0,0 +1,3 @@ +InteropTestsClient and InteropTestsWebsite are copied from [grpc-dotnet](https://github.com/grpc/grpc-dotnet/tree/master/testassets). + +For more information about the interop tests, see the [interop tests specification](https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md). diff --git a/src/ProjectTemplates/test/Helpers/AspNetProcess.cs b/src/ProjectTemplates/test/Helpers/AspNetProcess.cs index 753eb1258a52..86724b970fb9 100644 --- a/src/ProjectTemplates/test/Helpers/AspNetProcess.cs +++ b/src/ProjectTemplates/test/Helpers/AspNetProcess.cs @@ -11,6 +11,7 @@ using AngleSharp.Dom.Html; using AngleSharp.Parser.Html; using Microsoft.AspNetCore.Certificates.Generation; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging.Abstractions; diff --git a/src/ProjectTemplates/test/Helpers/ErrorMessages.cs b/src/ProjectTemplates/test/Helpers/ErrorMessages.cs index c63f008f831a..744ada299bfb 100644 --- a/src/ProjectTemplates/test/Helpers/ErrorMessages.cs +++ b/src/ProjectTemplates/test/Helpers/ErrorMessages.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.AspNetCore.Internal; + namespace Templates.Test.Helpers { internal static class ErrorMessages diff --git a/src/ProjectTemplates/test/Helpers/Project.cs b/src/ProjectTemplates/test/Helpers/Project.cs index 3fdcdf9d0ce2..b16801a5f748 100644 --- a/src/ProjectTemplates/test/Helpers/Project.cs +++ b/src/ProjectTemplates/test/Helpers/Project.cs @@ -10,6 +10,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Internal; using Microsoft.Extensions.CommandLineUtils; using Xunit; using Xunit.Abstractions; diff --git a/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs b/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs index 3eed004ef60a..5c94fde2b49b 100644 --- a/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs +++ b/src/ProjectTemplates/test/Helpers/TemplatePackageInstaller.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Internal; using Microsoft.Extensions.CommandLineUtils; using Xunit; using Xunit.Abstractions; diff --git a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs b/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs index bd393b8d5865..d702e01be1e6 100644 --- a/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs +++ b/src/ProjectTemplates/test/SpaTemplateTest/SpaTemplateTestBase.cs @@ -10,6 +10,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.AspNetCore.E2ETesting; +using Microsoft.AspNetCore.Internal; using Newtonsoft.Json.Linq; using OpenQA.Selenium; using Templates.Test.Helpers; diff --git a/src/ProjectTemplates/test/Helpers/ProcessEx.cs b/src/Shared/Process/ProcessEx.cs similarity index 99% rename from src/ProjectTemplates/test/Helpers/ProcessEx.cs rename to src/Shared/Process/ProcessEx.cs index db132bdafe07..c1743a2f0a96 100644 --- a/src/ProjectTemplates/test/Helpers/ProcessEx.cs +++ b/src/Shared/Process/ProcessEx.cs @@ -15,7 +15,7 @@ using Microsoft.Extensions.Internal; using Xunit.Abstractions; -namespace Templates.Test.Helpers +namespace Microsoft.AspNetCore.Internal { internal class ProcessEx : IDisposable { @@ -100,7 +100,7 @@ public static ProcessEx Run(ITestOutputHelper output, string workingDirectory, s } startInfo.EnvironmentVariables["NUGET_PACKAGES"] = NUGET_PACKAGES; - + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix"))) { startInfo.EnvironmentVariables["NUGET_FALLBACK_PACKAGES"] = Environment.GetEnvironmentVariable("NUGET_FALLBACK_PACKAGES"); @@ -195,7 +195,7 @@ public void WaitForExit(bool assertSuccess, TimeSpan? timeSpan = null) } } - private static string GetNugetPackagesRestorePath() => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("NUGET_RESTORE"))) + private static string GetNugetPackagesRestorePath() => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("NUGET_RESTORE"))) ? typeof(ProcessEx).Assembly .GetCustomAttributes() .First(attribute => attribute.Key == "TestPackageRestorePath")