public void LambdaFunctionTest()
        {
            const string HELLO_SCRIPT = 
@"console.log('Loading http')
 
exports.handler = function (request, response) {
    response.write(""Hello, world!"");
    response.end();
    console.log(""Request completed"");
}";
            MemoryStream stream = new MemoryStream();
            using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
            {
                var entry = archive.CreateEntry("helloworld.js");
                using (var entryStream = entry.Open())
                using (var writer = new StreamWriter(entryStream))
                {
                    writer.Write(HELLO_SCRIPT);
                }
            }
            stream.Position = 0;

            var functionName = "HelloWorld";
            bool uploaded = false;

            var iamRoleName = "Lambda-" + DateTime.Now.Ticks;
            bool iamRoleCreated = false;
            try
            {
                var iamCreateResponse = iamClient.CreateRole(new CreateRoleRequest
                    {
                        RoleName = iamRoleName,
                        AssumeRolePolicyDocument = LAMBDA_ASSUME_ROLE_POLICY
                    });

                var statement = new Statement(Statement.StatementEffect.Allow);
                statement.Actions.Add(S3ActionIdentifiers.PutObject);
                statement.Actions.Add(S3ActionIdentifiers.GetObject);
                statement.Resources.Add(new Resource("*"));


                var policy = new Policy();
                policy.Statements.Add(statement);

                iamClient.PutRolePolicy(new PutRolePolicyRequest
                    {
                        RoleName = iamRoleName,
                        PolicyName = "admin",
                        PolicyDocument = policy.ToJson()
                    });

                // Wait for the role and policy to propagate
                Thread.Sleep(5000);

                var uploadRequest = new UploadFunctionRequest
                {
                    FunctionName = functionName,
                    FunctionZip = stream,
                    Handler = "helloworld.handler",
                    Mode = Mode.Event,
                    Runtime = Runtime.Nodejs,
                    Role = iamCreateResponse.Role.Arn
                };

                var uploadResponse = lambdaClient.UploadFunction(uploadRequest);
                uploaded = true;
                Assert.IsTrue(uploadResponse.CodeSize > 0);
                Assert.IsNotNull(uploadResponse.ConfigurationId);

                // List all the functions and make sure the newly uploaded function is in the collection
                var listResponse = lambdaClient.ListFunctions();
                var function = listResponse.Functions.FirstOrDefault(x => x.FunctionName == functionName);
                Assert.IsNotNull(function);
                Assert.AreEqual("helloworld.handler", function.Handler);
                Assert.AreEqual(iamCreateResponse.Role.Arn, function.Role);

                // Get the function with a presigned URL to the uploaded code
                var getFunctionResponse = lambdaClient.GetFunction(functionName);
                Assert.AreEqual("helloworld.handler", getFunctionResponse.Configuration.Handler);
                Assert.IsNotNull(getFunctionResponse.Code.Location);

                // Get the function's configuration only
                var getFunctionConfiguration = lambdaClient.GetFunctionConfiguration(functionName);
                Assert.AreEqual("helloworld.handler", getFunctionConfiguration.Handler);

                // Call the function
                var invokeResponse = lambdaClient.InvokeAsync(functionName);
                Assert.AreEqual(invokeResponse.Status, 202); // Status Code Accepted

            }
            finally
            {
                if(uploaded)
                    lambdaClient.DeleteFunction(functionName);

                if (iamRoleCreated)
                    iamClient.DeleteRole(new DeleteRoleRequest { RoleName = iamRoleName });
            }
        }
        internal UploadFunctionResponse UploadFunction(UploadFunctionRequest request)
        {
            var marshaller = new UploadFunctionRequestMarshaller();
            var unmarshaller = UploadFunctionResponseUnmarshaller.Instance;

            return Invoke<UploadFunctionRequest,UploadFunctionResponse>(request, marshaller, unmarshaller);
        }
        /// <summary>
        /// Initiates the asynchronous execution of the UploadFunction operation.
        /// </summary>
        /// 
        /// <param name="request">Container for the necessary parameters to execute the UploadFunction operation.</param>
        /// <param name="cancellationToken">
        ///     A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public Task<UploadFunctionResponse> UploadFunctionAsync(UploadFunctionRequest request, System.Threading.CancellationToken cancellationToken = default(CancellationToken))
        {
            var marshaller = new UploadFunctionRequestMarshaller();
            var unmarshaller = UploadFunctionResponseUnmarshaller.Instance;

            return InvokeAsync<UploadFunctionRequest,UploadFunctionResponse>(request, marshaller, 
                unmarshaller, cancellationToken);
        }
        /// <summary>
        /// Initiates the asynchronous execution of the UploadFunction operation.
        /// </summary>
        /// 
        /// <param name="request">Container for the necessary parameters to execute the UploadFunction operation on AmazonLambdaClient.</param>
        /// <param name="callback">An AsyncCallback delegate that is invoked when the operation completes.</param>
        /// <param name="state">A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback
        ///          procedure using the AsyncState property.</param>
        /// 
        /// <returns>An IAsyncResult that can be used to poll or wait for results, or both; this value is also needed when invoking EndUploadFunction
        ///         operation.</returns>
        public IAsyncResult BeginUploadFunction(UploadFunctionRequest request, AsyncCallback callback, object state)
        {
            var marshaller = new UploadFunctionRequestMarshaller();
            var unmarshaller = UploadFunctionResponseUnmarshaller.Instance;

            return BeginInvoke<UploadFunctionRequest>(request, marshaller, unmarshaller,
                callback, state);
        }