public async Task ToRpc_Collection_Long_With_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);
            MapField <string, string> addedCapabilities = new MapField <string, string>
            {
                { RpcWorkerConstants.TypedDataCollection, RpcWorkerConstants.TypedDataCollection }
            };

            capabilities.UpdateCapabilities(addedCapabilities);
            long[]    arrLong           = { 1L, 2L };
            TypedData returned_typedata = await arrLong.ToRpc(logger, capabilities);

            TypedData        typedData      = new TypedData();
            CollectionSInt64 collectionLong = new CollectionSInt64();

            foreach (long element in arrLong)
            {
                collectionLong.Sint64.Add(element);
            }
            typedData.CollectionSint64 = collectionLong;

            Assert.Equal(typedData.CollectionSint64, returned_typedata.CollectionSint64);
            Assert.Equal(typedData.CollectionSint64.Sint64[0], returned_typedata.CollectionSint64.Sint64[0]);
        }
        public async Task ToRpc_Collection_Double_With_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);
            MapField <string, string> addedCapabilities = new MapField <string, string>
            {
                { RpcWorkerConstants.TypedDataCollection, RpcWorkerConstants.TypedDataCollection }
            };

            capabilities.UpdateCapabilities(addedCapabilities);
            double[]  arrDouble         = { 1.1, 2.2 };
            TypedData returned_typedata = await arrDouble.ToRpc(logger, capabilities);

            TypedData typedData = new TypedData();

            CollectionDouble collectionDouble = new CollectionDouble();

            foreach (double element in arrDouble)
            {
                collectionDouble.Double.Add(element);
            }
            typedData.CollectionDouble = collectionDouble;

            Assert.Equal(typedData.CollectionDouble, returned_typedata.CollectionDouble);
            Assert.Equal(typedData.CollectionDouble.Double[0], returned_typedata.CollectionDouble.Double[0]);
        }
        public async Task ToRpc_Collection_String_With_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);
            MapField <string, string> addedCapabilities = new MapField <string, string>
            {
                { RpcWorkerConstants.TypedDataCollection, RpcWorkerConstants.TypedDataCollection }
            };

            capabilities.UpdateCapabilities(addedCapabilities);
            string[]  arrString         = { "element1", "element_2" };
            TypedData returned_typedata = await arrString.ToRpc(logger, capabilities);

            TypedData        typedData        = new TypedData();
            CollectionString collectionString = new CollectionString();

            foreach (string element in arrString)
            {
                if (!string.IsNullOrEmpty(element))
                {
                    collectionString.String.Add(element);
                }
            }
            typedData.CollectionString = collectionString;

            Assert.Equal(typedData.CollectionString, returned_typedata.CollectionString);
            Assert.Equal(typedData.CollectionString.String[0], returned_typedata.CollectionString.String[0]);
        }
        public async Task ToRpc_Collection_Byte_With_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);
            MapField <string, string> addedCapabilities = new MapField <string, string>
            {
                { RpcWorkerConstants.TypedDataCollection, RpcWorkerConstants.TypedDataCollection }
            };

            capabilities.UpdateCapabilities(addedCapabilities);

            byte[][] arrBytes = new byte[2][];
            arrBytes[0] = new byte[] { 22 };
            arrBytes[1] = new byte[] { 11 };

            TypedData returned_typedata = await arrBytes.ToRpc(logger, capabilities);

            TypedData typedData = new TypedData();

            CollectionBytes collectionBytes = new CollectionBytes();

            foreach (byte[] element in arrBytes)
            {
                if (element != null)
                {
                    collectionBytes.Bytes.Add(ByteString.CopyFrom(element));
                }
            }
            typedData.CollectionBytes = collectionBytes;

            Assert.Equal(typedData.CollectionBytes, returned_typedata.CollectionBytes);
            Assert.Equal(typedData.CollectionBytes.Bytes[0], returned_typedata.CollectionBytes.Bytes[0]);
        }
        public async Task HttpObjects_Headers(bool ignoreEmptyValues, string[] headerKeys, string[] headerValues, string[] expectedKeys, string[] expectedValues)
        {
            var logger = MockNullLoggerFactory.CreateLogger();
            // Capability must be enabled
            var capabilities = new GrpcCapabilities(logger);

            if (ignoreEmptyValues)
            {
                capabilities.UpdateCapabilities(new MapField <string, string>
                {
                    { RpcWorkerConstants.IgnoreEmptyValuedRpcHttpHeaders, "true" }
                });
            }

            var headerDictionary = new HeaderDictionary();

            for (int i = 0; i < headerValues.Length; i++)
            {
                headerDictionary.Add(headerKeys[i], headerValues[i]);
            }

            HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", $"http://localhost/api/httptrigger-scenarios", headerDictionary);

            var rpcRequestObject = await request.ToRpc(logger, capabilities);

            // Same key and value strings for each pair
            for (int i = 0; i < expectedKeys.Length; i++)
            {
                Assert.True(rpcRequestObject.Http.Headers.ContainsKey(expectedKeys[i]));
                Assert.Equal(expectedValues[i], rpcRequestObject.Http.Headers.GetValueOrDefault(expectedKeys[i]));
            }
        }
        public async Task ToRpc_Collection_Double_Without_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            double[]  arrDouble         = { 1.1, 2.2 };
            TypedData returned_typedata = await arrDouble.ToRpc(logger, capabilities);

            TypedData typedData = new TypedData();

            typedData.Json = JsonConvert.SerializeObject(arrDouble);

            Assert.Equal(typedData.Json, returned_typedata.Json);
        }
        public async Task ToRpc_Collection_String_Without_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            string[]  arrString         = { "element1", "element_2" };
            TypedData returned_typedata = await arrString.ToRpc(logger, capabilities);

            TypedData typedData = new TypedData();

            typedData.Json = JsonConvert.SerializeObject(arrString);

            Assert.Equal(typedData.Json, returned_typedata.Json);
        }
        public async Task ToRpc_Bytes_Without_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            byte[] arrByte = Encoding.Default.GetBytes("HellowWorld");

            TypedData returned_typedata = await arrByte.ToRpc(logger, capabilities);

            TypedData typedData = new TypedData();

            typedData.Bytes = ByteString.CopyFrom(arrByte);

            Assert.Equal(typedData.Bytes, returned_typedata.Bytes);
        }
        public async Task HttpObjects_ClaimsPrincipal()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", $"http://localhost/apihttptrigger-scenarios");

            var claimsIdentity1 = MockEasyAuth("facebook", "Connor McMahon", "10241897674253170");
            var claimsIdentity2 = new ClaimsIdentity(new List <Claim>
            {
                new Claim("http://schemas.microsoft.com/2017/07/functions/claims/authlevel", "Function")
            }, "WebJobsAuthLevel");
            var claimsIdentity3  = new ClaimsIdentity();
            var claimsIdentities = new List <ClaimsIdentity> {
                claimsIdentity1, claimsIdentity2, claimsIdentity3
            };

            request.HttpContext.User = new ClaimsPrincipal(claimsIdentities);

            var rpcRequestObject = await request.ToRpc(logger, capabilities);

            var identities    = request.HttpContext.User.Identities.ToList();
            var rpcIdentities = rpcRequestObject.Http.Identities.ToList();

            Assert.Equal(claimsIdentities.Count, rpcIdentities.Count);

            for (int i = 0; i < identities.Count; i++)
            {
                var identity    = identities[i];
                var rpcIdentity = rpcIdentities.ElementAtOrDefault(i);

                Assert.NotNull(identity);
                Assert.NotNull(rpcIdentity);

                Assert.Equal(rpcIdentity.AuthenticationType?.Value, identity.AuthenticationType);
                Assert.Equal(rpcIdentity.NameClaimType?.Value, identity.NameClaimType);
                Assert.Equal(rpcIdentity.RoleClaimType?.Value, identity.RoleClaimType);

                var claims = identity.Claims.ToList();
                for (int j = 0; j < claims.Count; j++)
                {
                    Assert.True(rpcIdentity.Claims.ElementAtOrDefault(j) != null);
                    Assert.Equal(rpcIdentity.Claims[j].Type, claims[j].Type);
                    Assert.Equal(rpcIdentity.Claims[j].Value, claims[j].Value);
                }
            }
        }
        public async Task ToRpc_Collection_Byte_Without_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            byte[][] arrByte = new byte[2][];
            arrByte[0] = new byte[] { 22 };
            arrByte[1] = new byte[] { 11 };

            TypedData returned_typedata = await arrByte.ToRpc(logger, capabilities);

            TypedData typedData = new TypedData();

            typedData.Json = JsonConvert.SerializeObject(arrByte);

            Assert.Equal(typedData.Json, returned_typedata.Json);
        }
        [InlineData("say=Hi&to=", new string[] { "say" }, new string[] { "Hi" })] // Removes empty value query params
        public async Task HttpObjects_Query(string queryString, string[] expectedKeys, string[] expectedValues)
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", $"http://localhost/api/httptrigger-scenarios?{queryString}");

            var rpcRequestObject = await request.ToRpc(logger, capabilities);

            // Same number of expected key value pairs
            Assert.Equal(rpcRequestObject.Http.Query.Count, expectedKeys.Length);
            Assert.Equal(rpcRequestObject.Http.Query.Count, expectedValues.Length);
            // Same key and value strings for each pair
            for (int i = 0; i < expectedKeys.Length; i++)
            {
                Assert.True(rpcRequestObject.Http.Query.ContainsKey(expectedKeys[i]));
                Assert.Equal(rpcRequestObject.Http.Query.GetValueOrDefault(expectedKeys[i]), expectedValues[i]);
            }
        }
        public async Task ToRpc_Bytes_With_Capabilities_Value()
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);
            MapField <string, string> addedCapabilities = new MapField <string, string>
            {
                { RpcWorkerConstants.TypedDataCollection, RpcWorkerConstants.TypedDataCollection }
            };

            capabilities.UpdateCapabilities(addedCapabilities);
            byte[] arrByte = Encoding.Default.GetBytes("HellowWorld");

            TypedData returned_typedata = await arrByte.ToRpc(logger, capabilities);

            TypedData typedData = new TypedData();

            typedData.Bytes = ByteString.CopyFrom(arrByte);

            Assert.Equal(typedData.Bytes, returned_typedata.Bytes);
        }
        public async Task HttpObjects_RawBodyBytes_Image_Length(string contentType, string rawBytesEnabled)
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            if (!string.Equals(rawBytesEnabled, null))
            {
                capabilities.UpdateCapabilities(new MapField <string, string>
                {
                    { RpcWorkerConstants.RawHttpBodyBytes, rawBytesEnabled.ToString() }
                });
            }

            FileStream image = new FileStream(TestImageLocation, FileMode.Open, FileAccess.Read);

            byte[] imageBytes  = FileStreamToBytes(image);
            string imageString = Encoding.UTF8.GetString(imageBytes);

            long imageBytesLength  = imageBytes.Length;
            long imageStringLength = imageString.Length;

            var headers = new HeaderDictionary();

            headers.Add("content-type", contentType);
            HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", "http://localhost/api/httptrigger-scenarios", headers, imageBytes);

            var rpcRequestObject = await request.ToRpc(logger, capabilities);

            if (string.IsNullOrEmpty(rawBytesEnabled))
            {
                Assert.Empty(rpcRequestObject.Http.RawBody.Bytes);
                Assert.Equal(imageStringLength, rpcRequestObject.Http.RawBody.String.Length);
            }
            else
            {
                Assert.Empty(rpcRequestObject.Http.RawBody.String);
                Assert.Equal(imageBytesLength, rpcRequestObject.Http.RawBody.Bytes.ToByteArray().Length);
            }
        }
        public async Task HttpTrigger_Post_ByteArray(string expectedContentType, bool rcpHttpBodyOnly)
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            if (rcpHttpBodyOnly)
            {
                capabilities.UpdateCapabilities(new MapField <string, string>
                {
                    { RpcWorkerConstants.RpcHttpBodyOnly, rcpHttpBodyOnly.ToString() }
                });
            }

            var headers = new HeaderDictionary();

            headers.Add("content-type", expectedContentType);
            byte[] body = new byte[] { 1, 2, 3, 4, 5 };

            HttpRequest request = HttpTestHelpers.CreateHttpRequest("POST", "http://localhost/api/httptrigger-scenarios", headers, body);

            var rpcRequestObject = await request.ToRpc(logger, capabilities);

            if (rcpHttpBodyOnly)
            {
                Assert.Equal(null, rpcRequestObject.Http.RawBody);
                Assert.Equal(body, rpcRequestObject.Http.Body.Bytes);
            }
            else
            {
                Assert.Equal(body, rpcRequestObject.Http.Body.Bytes);
                Assert.Equal(Encoding.UTF8.GetString(body), rpcRequestObject.Http.RawBody.String);
            }

            string contentType;

            rpcRequestObject.Http.Headers.TryGetValue("content-type", out contentType);
            Assert.Equal(expectedContentType, contentType);
        }
        public async Task HttpObjects_JsonBody(string expectedContentType, string body, bool rcpHttpBodyOnly)
        {
            var logger       = MockNullLoggerFactory.CreateLogger();
            var capabilities = new GrpcCapabilities(logger);

            if (rcpHttpBodyOnly)
            {
                capabilities.UpdateCapabilities(new MapField <string, string>
                {
                    { RpcWorkerConstants.RpcHttpBodyOnly, rcpHttpBodyOnly.ToString() }
                });
            }

            var headers = new HeaderDictionary();

            headers.Add("content-type", expectedContentType);
            HttpRequest request = HttpTestHelpers.CreateHttpRequest("GET", "http://localhost/api/httptrigger-scenarios", headers, body);

            var rpcRequestObject = await request.ToRpc(logger, capabilities);

            if (rcpHttpBodyOnly)
            {
                Assert.Equal(null, rpcRequestObject.Http.RawBody);
                Assert.Equal(body.ToString(), rpcRequestObject.Http.Body.String);
            }
            else
            {
                Assert.Equal(body.ToString(), rpcRequestObject.Http.RawBody.String);
                Assert.Equal(JsonConvert.DeserializeObject(body), JsonConvert.DeserializeObject(rpcRequestObject.Http.Body.Json));
            }

            string contentType;

            rpcRequestObject.Http.Headers.TryGetValue("content-type", out contentType);
            Assert.Equal(expectedContentType, contentType);
        }
示例#16
0
        public async Task ToRpcInvocationRequest_RpcSharedMemoryDataTransfer()
        {
            var logger = new TestLogger("test");

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Host   = new HostString("local");
            httpContext.Request.Path   = "/test";
            httpContext.Request.Method = "Post";

            var poco = new TestPoco {
                Id = 1, Name = "Test"
            };

            var bindingData = new Dictionary <string, object>
            {
                { "req", httpContext.Request },
                { "$request", httpContext.Request },
                { "headers", httpContext.Request.Headers.ToDictionary(p => p.Key, p => p.Value) },
                { "query", httpContext.Request.QueryString.ToString() },
                { "sys", new SystemBindingData() }
            };

            const int inputStringLength = 2 * 1024 * 1024;
            string    inputString       = TestUtils.GetRandomString(inputStringLength);

            const int inputBytesLength = 2 * 1024 * 1024;

            byte[] inputBytes = TestUtils.GetRandomBytesInArray(inputBytesLength);

            var inputs = new List <(string name, DataType type, object val)>
            {
                ("req", DataType.String, httpContext.Request),
                ("fooStr", DataType.String, inputString),
                ("fooBytes", DataType.Binary, inputBytes),
            };

            var invocationContext = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
                {
                    InvocationId = Guid.NewGuid(),
                    FunctionName = "Test",
                },
                BindingData           = bindingData,
                Inputs                = inputs,
                ResultSource          = new TaskCompletionSource <ScriptInvocationResult>(),
                Logger                = logger,
                AsyncExecutionContext = System.Threading.ExecutionContext.Capture()
            };

            var functionMetadata = new FunctionMetadata
            {
                Name = "Test"
            };

            var httpTriggerBinding = new BindingMetadata
            {
                Name      = "req",
                Type      = "httpTrigger",
                Direction = BindingDirection.In,
                Raw       = new JObject()
            };

            var fooStrInputBinding = new BindingMetadata
            {
                Name      = "fooStr",
                Type      = "fooStr",
                Direction = BindingDirection.In
            };

            var fooBytesInputBinding = new BindingMetadata
            {
                Name      = "fooBytes",
                Type      = "fooBytes",
                Direction = BindingDirection.In
            };

            var httpOutputBinding = new BindingMetadata
            {
                Name      = "res",
                Type      = "http",
                Direction = BindingDirection.Out,
                Raw       = new JObject(),
                DataType  = DataType.String
            };

            functionMetadata.Bindings.Add(httpTriggerBinding);
            functionMetadata.Bindings.Add(fooStrInputBinding);
            functionMetadata.Bindings.Add(fooBytesInputBinding);
            functionMetadata.Bindings.Add(httpOutputBinding);
            invocationContext.FunctionMetadata = functionMetadata;

            GrpcCapabilities capabilities = new GrpcCapabilities(logger);
            var result = await invocationContext.ToRpcInvocationRequest(logger, capabilities, isSharedMemoryDataTransferEnabled : true, _sharedMemoryManager);

            Assert.Equal(3, result.InputData.Count);

            Assert.Equal("fooStr", result.InputData[1].Name);
            Assert.Equal("fooBytes", result.InputData[2].Name);

            // The input data should be transferred over shared memory
            RpcSharedMemory sharedMem1 = result.InputData[1].RpcSharedMemory;

            // This is what the expected byte[] representation of the string should be
            // We use that to find expected length
            byte[] contentBytes = Encoding.UTF8.GetBytes(inputString);
            Assert.Equal(contentBytes.Length, sharedMem1.Count);

            // Check that the name of the shared memory map is a valid GUID
            Assert.True(Guid.TryParse(sharedMem1.Name, out _));

            // Check the type being sent
            Assert.Equal(sharedMem1.Type, RpcDataType.String);

            // The input data should be transferred over shared memory
            RpcSharedMemory sharedMem2 = result.InputData[2].RpcSharedMemory;

            Assert.Equal(inputBytes.Length, sharedMem2.Count);

            // Check that the name of the shared memory map is a valid GUID
            Assert.True(Guid.TryParse(sharedMem2.Name, out _));

            // Check the type being sent
            Assert.Equal(sharedMem2.Type, RpcDataType.Bytes);
        }
示例#17
0
        public async Task ToRpcInvocationRequest_Http_OmitsDuplicateBodyOfBindingData()
        {
            var logger = new TestLogger("test");

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Host   = new HostString("local");
            httpContext.Request.Path   = "/test";
            httpContext.Request.Method = "Post";

            var inputs = new List <(string name, DataType type, object val)>
            {
                ("req", DataType.String, httpContext.Request)
            };

            var bindingData = new Dictionary <string, object>
            {
                { "req", httpContext.Request },
                { "$request", httpContext.Request },
                { "headers", httpContext.Request.Headers.ToDictionary(p => p.Key, p => p.Value) },
                { "query", httpContext.Request.QueryString.ToString() },
                { "sys", new SystemBindingData() }
            };

            var invocationContext = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
                {
                    InvocationId = Guid.NewGuid(),
                    FunctionName = "Test",
                },
                BindingData           = bindingData,
                Inputs                = inputs,
                ResultSource          = new TaskCompletionSource <ScriptInvocationResult>(),
                Logger                = logger,
                AsyncExecutionContext = System.Threading.ExecutionContext.Capture()
            };

            var functionMetadata = new FunctionMetadata
            {
                Name = "Test"
            };

            var httpTriggerBinding = new BindingMetadata
            {
                Name      = "req",
                Type      = "httpTrigger",
                Direction = BindingDirection.In,
                Raw       = new JObject()
            };

            var httpOutputBinding = new BindingMetadata
            {
                Name      = "res",
                Type      = "http",
                Direction = BindingDirection.Out,
                Raw       = new JObject(),
                DataType  = DataType.String
            };

            functionMetadata.Bindings.Add(httpTriggerBinding);
            functionMetadata.Bindings.Add(httpOutputBinding);
            invocationContext.FunctionMetadata = functionMetadata;

            GrpcCapabilities          capabilities      = new GrpcCapabilities(logger);
            MapField <string, string> addedCapabilities = new MapField <string, string>
            {
                { RpcWorkerConstants.RpcHttpTriggerMetadataRemoved, "1" },
                { RpcWorkerConstants.RpcHttpBodyOnly, "1" }
            };

            capabilities.UpdateCapabilities(addedCapabilities);

            var result = await invocationContext.ToRpcInvocationRequest(logger, capabilities, isSharedMemoryDataTransferEnabled : false, _sharedMemoryManager);

            Assert.Equal(1, result.InputData.Count);
            Assert.Equal(2, result.TriggerMetadata.Count);
            Assert.True(result.TriggerMetadata.ContainsKey("headers"));
            Assert.True(result.TriggerMetadata.ContainsKey("query"));
        }
示例#18
0
        public async Task ToRpcInvocationRequest_MultipleInputBindings()
        {
            var logger = new TestLogger("test");

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Host   = new HostString("local");
            httpContext.Request.Path   = "/test";
            httpContext.Request.Method = "Post";

            var poco = new TestPoco {
                Id = 1, Name = "Test"
            };

            var bindingData = new Dictionary <string, object>
            {
                { "req", httpContext.Request },
                { "$request", httpContext.Request },
                { "headers", httpContext.Request.Headers.ToDictionary(p => p.Key, p => p.Value) },
                { "query", httpContext.Request.QueryString.ToString() },
                { "sys", new SystemBindingData() }
            };

            var inputs = new List <(string name, DataType type, object val)>
            {
                ("req", DataType.String, httpContext.Request),
                ("blob", DataType.String, null),  // verify that null values are handled
                ("foo", DataType.String, "test"),
                ("bar1", DataType.String, poco),
                ("bar2", DataType.String, poco)
            };

            var invocationContext = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
                {
                    InvocationId = Guid.NewGuid(),
                    FunctionName = "Test",
                },
                BindingData           = bindingData,
                Inputs                = inputs,
                ResultSource          = new TaskCompletionSource <ScriptInvocationResult>(),
                Logger                = logger,
                AsyncExecutionContext = System.Threading.ExecutionContext.Capture()
            };

            var functionMetadata = new FunctionMetadata
            {
                Name = "Test"
            };

            var httpTriggerBinding = new BindingMetadata
            {
                Name      = "req",
                Type      = "httpTrigger",
                Direction = BindingDirection.In,
                Raw       = new JObject()
            };

            var blobInputBinding = new BindingMetadata
            {
                Name      = "blob",
                Type      = "blob",
                Direction = BindingDirection.In
            };

            var fooInputBinding = new BindingMetadata
            {
                Name      = "foo",
                Type      = "foo",
                Direction = BindingDirection.In
            };

            var barInputBinding1 = new BindingMetadata
            {
                Name      = "bar1",
                Type      = "bar",
                Direction = BindingDirection.In
            };

            var barInputBinding2 = new BindingMetadata
            {
                Name      = "bar2",
                Type      = "bar",
                Direction = BindingDirection.In
            };

            var httpOutputBinding = new BindingMetadata
            {
                Name      = "res",
                Type      = "http",
                Direction = BindingDirection.Out,
                Raw       = new JObject(),
                DataType  = DataType.String
            };

            functionMetadata.Bindings.Add(httpTriggerBinding);
            functionMetadata.Bindings.Add(blobInputBinding);
            functionMetadata.Bindings.Add(fooInputBinding);
            functionMetadata.Bindings.Add(barInputBinding1);
            functionMetadata.Bindings.Add(barInputBinding2);
            functionMetadata.Bindings.Add(httpOutputBinding);
            invocationContext.FunctionMetadata = functionMetadata;

            GrpcCapabilities capabilities = new GrpcCapabilities(logger);
            var result = await invocationContext.ToRpcInvocationRequest(logger, capabilities, isSharedMemoryDataTransferEnabled : false, _sharedMemoryManager);

            Assert.Equal(5, result.InputData.Count);

            Assert.Equal("req", result.InputData[0].Name);
            var resultHttp = result.InputData[0].Data;

            Assert.Equal("http://local/test", ((RpcHttp)result.InputData[0].Data.Http).Url);

            // verify the null input was propagated properly
            Assert.Equal("blob", result.InputData[1].Name);
            Assert.Equal(string.Empty, result.InputData[1].Data.String);

            Assert.Equal("foo", result.InputData[2].Name);
            Assert.Equal("test", result.InputData[2].Data.String);

            Assert.Equal("bar1", result.InputData[3].Name);
            var resultPoco = result.InputData[3].Data;

            Assert.Equal("{\"Name\":\"Test\",\"Id\":1}", resultPoco.Json);

            Assert.Equal("bar2", result.InputData[4].Name);
            Assert.Same(resultPoco, result.InputData[4].Data);

            Assert.Equal(4, result.TriggerMetadata.Count);
            Assert.Same(resultHttp, result.TriggerMetadata["req"]);
            Assert.Same(resultHttp, result.TriggerMetadata["$request"]);
            Assert.True(result.TriggerMetadata.ContainsKey("headers"));
            Assert.True(result.TriggerMetadata.ContainsKey("query"));
        }
        public async Task ToRpcInvocationRequest_RpcSharedMemoryDataTransfer_UsingFunctionDataCache_CacheMiss()
        {
            var logger = new TestLogger("test");

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Host   = new HostString("local");
            httpContext.Request.Path   = "/test";
            httpContext.Request.Method = "Post";

            var poco = new TestPoco {
                Id = 1, Name = "Test"
            };

            var bindingData = new Dictionary <string, object>
            {
                { "req", httpContext.Request },
                { "$request", httpContext.Request },
                { "headers", httpContext.Request.Headers.ToDictionary(p => p.Key, p => p.Value) },
                { "query", httpContext.Request.QueryString.ToString() },
                { "sys", new SystemBindingData() }
            };

            const int    inputStringLength  = 2 * 1024 * 1024;
            string       inputString        = TestUtils.GetRandomString(inputStringLength);
            Stream       inputStream1       = new MemoryStream();
            StreamWriter inputStreamWriter1 = new StreamWriter(inputStream1);
            await inputStreamWriter1.WriteAsync(inputString);

            await inputStreamWriter1.FlushAsync();

            inputStream1.Seek(0, SeekOrigin.Begin);

            FunctionDataCacheKey     key1      = new FunctionDataCacheKey("fooStr", "0x1");
            MockCacheAwareReadObject cacheObj1 = new MockCacheAwareReadObject(key1, inputStream1, _functionDataCache);

            const int inputBytesLength = 2 * 1024 * 1024;

            byte[] inputBytes   = TestUtils.GetRandomBytesInArray(inputBytesLength);
            Stream inputStream2 = new MemoryStream(inputBytes);

            inputStream2.Seek(0, SeekOrigin.Begin);

            FunctionDataCacheKey     key2      = new FunctionDataCacheKey("fooBytes", "0x1");
            MockCacheAwareReadObject cacheObj2 = new MockCacheAwareReadObject(key2, inputStream2, _functionDataCache);

            var inputs = new List <(string name, DataType type, object val)>
            {
                ("req", DataType.String, httpContext.Request),
                ("fooStr", DataType.String, cacheObj1),
                ("fooBytes", DataType.Binary, cacheObj2),
            };

            var invocationContext = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
                {
                    InvocationId = Guid.NewGuid(),
                    FunctionName = "Test",
                },
                BindingData           = bindingData,
                Inputs                = inputs,
                ResultSource          = new TaskCompletionSource <ScriptInvocationResult>(),
                Logger                = logger,
                AsyncExecutionContext = System.Threading.ExecutionContext.Capture()
            };

            var functionMetadata = new FunctionMetadata
            {
                Name = "Test"
            };

            var httpTriggerBinding = new BindingMetadata
            {
                Name      = "req",
                Type      = "httpTrigger",
                Direction = BindingDirection.In,
                Raw       = new JObject()
            };

            var fooStrInputBinding = new BindingMetadata
            {
                Name      = "fooStr",
                Type      = "fooStr",
                Direction = BindingDirection.In
            };

            var fooBytesInputBinding = new BindingMetadata
            {
                Name      = "fooBytes",
                Type      = "fooBytes",
                Direction = BindingDirection.In
            };

            var httpOutputBinding = new BindingMetadata
            {
                Name      = "res",
                Type      = "http",
                Direction = BindingDirection.Out,
                Raw       = new JObject(),
                DataType  = DataType.String
            };

            functionMetadata.Bindings.Add(httpTriggerBinding);
            functionMetadata.Bindings.Add(fooStrInputBinding);
            functionMetadata.Bindings.Add(fooBytesInputBinding);
            functionMetadata.Bindings.Add(httpOutputBinding);
            invocationContext.FunctionMetadata = functionMetadata;

            GrpcCapabilities capabilities = new GrpcCapabilities(logger);
            var result = await invocationContext.ToRpcInvocationRequest(logger, capabilities, isSharedMemoryDataTransferEnabled : true, _sharedMemoryManager);

            Assert.Equal(3, result.InputData.Count);

            Assert.Equal("fooStr", result.InputData[1].Name);
            Assert.Equal("fooBytes", result.InputData[2].Name);

            // The input data should be transferred over shared memory
            RpcSharedMemory sharedMem1 = result.InputData[1].RpcSharedMemory;

            // This is what the expected byte[] representation of the string should be
            // We use that to find expected length
            byte[] contentBytes = Encoding.UTF8.GetBytes(inputString);
            Assert.Equal(contentBytes.Length, sharedMem1.Count);

            // Check that the name of the shared memory map is a valid GUID
            Assert.True(Guid.TryParse(sharedMem1.Name, out _));

            // Check the type being sent
            Assert.Equal(sharedMem1.Type, RpcDataType.String);

            // The input data should be transferred over shared memory
            RpcSharedMemory sharedMem2 = result.InputData[2].RpcSharedMemory;

            Assert.Equal(inputBytes.Length, sharedMem2.Count);

            // Check that the name of the shared memory map is a valid GUID
            Assert.True(Guid.TryParse(sharedMem2.Name, out _));

            // Check the type being sent
            Assert.Equal(sharedMem2.Type, RpcDataType.Bytes);

            // Check that the inputs were inserted into shared memory
            object inputStringReadObj = await _sharedMemoryManager.GetObjectAsync(sharedMem1.Name, 0, (int)sharedMem1.Count, typeof(string));

            Assert.NotNull(inputStringReadObj);
            string inputStringRead = inputStringReadObj as string;

            Assert.Equal(inputString, inputStringRead);

            object inputBytesReadObj = await _sharedMemoryManager.GetObjectAsync(sharedMem2.Name, 0, (int)sharedMem2.Count, typeof(byte[]));

            Assert.NotNull(inputBytesReadObj);
            byte[] inputBytesRead = inputBytesReadObj as byte[];
            Assert.Equal(inputBytes, inputBytesRead);

            // Check that the inputs were not marked to be removed after the invocation
            Assert.Empty(_sharedMemoryManager.InvocationSharedMemoryMaps);

            // Check that the inputs were inserted into the cache
            Assert.True(_functionDataCache.TryGet(key1, isIncrementActiveReference: false, out _));
            Assert.True(_functionDataCache.TryGet(key2, isIncrementActiveReference: false, out _));
        }
示例#20
0
        public async Task ToRpcInvocationRequest_RpcDataTransfer()
        {
            var logger = new TestLogger("test");

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Host   = new HostString("local");
            httpContext.Request.Path   = "/test";
            httpContext.Request.Method = "Post";

            var poco = new TestPoco {
                Id = 1, Name = "Test"
            };

            var bindingData = new Dictionary <string, object>
            {
                { "req", httpContext.Request },
                { "$request", httpContext.Request },
                { "headers", httpContext.Request.Headers.ToDictionary(p => p.Key, p => p.Value) },
                { "query", httpContext.Request.QueryString.ToString() },
                { "sys", new SystemBindingData() }
            };

            const int inputStringLength = 32;
            string    inputString       = TestUtils.GetRandomString(inputStringLength);

            const int inputBytesLength = 32;

            byte[] inputBytes = TestUtils.GetRandomBytesInArray(inputBytesLength);

            var inputs = new List <(string name, DataType type, object val)>
            {
                ("req", DataType.String, httpContext.Request),
                ("fooStr", DataType.String, inputString),
                ("fooBytes", DataType.Binary, inputBytes),
            };

            var invocationContext = new ScriptInvocationContext()
            {
                ExecutionContext = new ExecutionContext()
                {
                    InvocationId = Guid.NewGuid(),
                    FunctionName = "Test",
                },
                BindingData           = bindingData,
                Inputs                = inputs,
                ResultSource          = new TaskCompletionSource <ScriptInvocationResult>(),
                Logger                = logger,
                AsyncExecutionContext = System.Threading.ExecutionContext.Capture()
            };

            var functionMetadata = new FunctionMetadata
            {
                Name = "Test"
            };

            var httpTriggerBinding = new BindingMetadata
            {
                Name      = "req",
                Type      = "httpTrigger",
                Direction = BindingDirection.In,
                Raw       = new JObject()
            };

            var fooStrInputBinding = new BindingMetadata
            {
                Name      = "fooStr",
                Type      = "fooStr",
                Direction = BindingDirection.In
            };

            var fooBytesInputBinding = new BindingMetadata
            {
                Name      = "fooBytes",
                Type      = "fooBytes",
                Direction = BindingDirection.In
            };

            var httpOutputBinding = new BindingMetadata
            {
                Name      = "res",
                Type      = "http",
                Direction = BindingDirection.Out,
                Raw       = new JObject(),
                DataType  = DataType.String
            };

            functionMetadata.Bindings.Add(httpTriggerBinding);
            functionMetadata.Bindings.Add(fooStrInputBinding);
            functionMetadata.Bindings.Add(fooBytesInputBinding);
            functionMetadata.Bindings.Add(httpOutputBinding);
            invocationContext.FunctionMetadata = functionMetadata;

            GrpcCapabilities capabilities = new GrpcCapabilities(logger);
            var result = await invocationContext.ToRpcInvocationRequest(logger, capabilities, isSharedMemoryDataTransferEnabled : true, _sharedMemoryManager);

            Assert.Equal(3, result.InputData.Count);

            Assert.Equal("fooStr", result.InputData[1].Name);
            Assert.Equal("fooBytes", result.InputData[2].Name);

            // The input data should be transferred over regular RPC despite enabling shared memory
            Assert.Equal(inputString, result.InputData[1].Data.String);
            Assert.Equal(inputBytes, result.InputData[2].Data.Bytes);
        }
示例#21
0
 public GrpcCapabilitiesTests()
 {
     _loggerProvider = new TestLoggerProvider();
     _loggerFactory.AddProvider(_loggerProvider);
     _capabilities = new GrpcCapabilities(_loggerFactory.CreateLogger <GrpcCapabilities>());
 }