text:
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#
-->

# Developing a new Runtime with the ActionLoop proxy

The [OpenWhisk runtime specification](actions-new.md) defines the expected behavior of an OpenWhisk runtime; you can choose to implement a new runtime from scratch by just following this specification. However, the fastest way to develop a new, compliant runtime is by reusing the *[ActionLoop proxy](https://github.com/apache/incubator-openwhisk-runtime-go#actionloop-runtime)* which already implements most of the specification and requires you to write code for just a few hooks to get a fully functional (and *fast*) runtime in a few hours or less.

## What is the ActionLoop proxy

The `ActionLoop proxy` is a runtime "engine", written in the [Go programming language](https://golang.org/), originally developed specifically to support the [OpenWhisk Go language runtime](https://github.com/apache/incubator-openwhisk-runtime-go). However, it was written in a  generic way such that it has since been adopted to implement OpenWhisk runtimes for Swift, PHP, Python, Rust, Java, Ruby and Crystal. Even though it was developed with compiled languages in mind it works equally well with scripting languages.

Using it, you can develop a new runtime in a fraction of the time needed for authoring a full-fledged runtime from scratch. This is due to the fact that you have only to write a command line protocol and not a fully-featured web server (with a small amount of corner cases to consider). The results should also produce a runtime that is fairly fast and responsive.  In fact, the ActionLoop proxy has also been adopted to improve the performance of existing runtimes like Python, Ruby, PHP, and Java where performance has improved by a factor between 2x to 20x.

### Precompilation of OpenWhisk Actions

In addition to being the basis for new runtime development,  ActionLoop runtimes can also support offline "precompilation" of OpenWhisk Action source files into a ZIP file that contains only the compiled binaries which are very fast to start once deployed. More information on this approach can be found here: [Precompiling Go Sources Offline](https://github.com/apache/incubator-openwhisk-runtime-go/blob/master/docs/DEPLOY.md#precompile) which describes how to do this for the Go language, but the approach applies to any language supported by ActionLoop.

# Tutorial - How to write a new runtime with the ActionLoop Proxy

This section contains a stepwise tutorial which will take you through the process of developing a new ActionLoop runtime using the Ruby language as the example.

## General development process

The general procedure for authoring a runtime with the `ActionLoop proxy` requires the following steps:

* building a docker image containing your target language compiler and the ActionLoop runtime.
* writing a simple line-oriented protocol in your target language.
* writing a compilation script for your target language.
* writing some mandatory tests for your language.

## ActionLoop Starter Kit

To facilitate the process, there is an `actionloop-starter-kit` in the [openwhisk-devtools](https://github.com/apache/incubator-openwhisk-devtools/tree/master/actionloop-starter-kit) GitHub repository, that implements a fully working runtime for Python.  It contains a stripped-down version of the real Python runtime (with some advanced features removed) along with guided, step-by-step instructions on how to translate it to a different target runtime language using Ruby as an example.

In short, the starter kit provides templates you can adapt in creating an ActionLoop runtime for each of the steps listed above, these include :

-checking out  the `actionloop-starter-kit` from the `incubator-openwhisk-devtools` repository
-editing the `Dockerfile` to create the target environment for your target language.
-converting (rewrite) the `launcher.py` script to an equivalent for script for your target language.
-editing the `compile` script to compile your action in your target language.
-writing the mandatory tests for your target language, by adapting the `ActionLoopPythonBasicTests.scala` file.

As a starting language, we chose Python since it is one of the more human-readable languages (can be  treated as `pseudo-code`). Do not worry, you should only need just enough Python knowledge to be able to rewrite `launcher.py` and edit the `compile` script for your target language.

Finally, you will need to update the `ActionLoopPythonBasicTests.scala` test file which, although written in the Scala language, only serves as a wrapper that you will use to embed your target language tests into.

## Notation

In each step of this tutorial, we typically show snippets of either terminal transcripts (i.e., commands and results) or "diffs" of changes to existing code files.

Within terminal transcript snippets, comments are prefixed with `#` character and commands are prefixed by the `$` character. Lines that follow commands may include sample output (from their execution) which can be used to verify against results in your local environment.

When snippets show changes to existing source files, lines without a prefix should be left "as is", lines with `-` should be removed and lines with  `+` should be added.

## Prerequisites

* Docker engine - please have a valid [docker engine installed](https://docs.docker.com/install/) that supports [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/) (i.e., Docker 17.05 or higher) and assure the Docker daemon is running.

```bash
# Verify docker version
$ docker --version
Docker version 18.09.3

# Verify docker is running
$ docker ps

# The result should be a valid response listing running processes
```

## Setup the development directory

So let's start to create our own `actionloop-demo-ruby-2.6` runtime. First, check out the `devtools` repository to access the starter kit, then move it in your home directory to work on it.

```bash
$ git clone https://github.com/apache/incubator-openwhisk-devtools
$ mv incubator-openwhisk-devtools/actionloop-starter-kit ~/actionloop-demo-ruby-v2.6
```

Now, take the directory `python3.7` and rename it to `ruby2.6` and use `sed` to fix the directory name references in the Gradle build files.

```bash
$ cd ~/actionloop-demo-ruby-v2.6
$ mv python3.7 ruby2.6
$ sed -i.bak -e 's/python3.7/ruby2.6/' settings.gradle
$ sed -i.bak -e 's/actionloop-demo-python-v3.7/actionloop-demo-ruby-v2.6/' ruby2.6/build.gradle
```

Let's check everything is fine building the image.

```bash
# building the image
$ ./gradlew distDocker
# ... intermediate output omitted ...
BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed
# checking the image is available
$ docker images actionloop-demo-ruby-v2.6
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
actionloop-demo-ruby-v2.6   latest              df3e77c9cd8f        2 minutes ago          94.3MB
```

At this point, we have built a new image named `actionloop-demo-ruby-v2.6`. However, despite having `Ruby` in the name, internally it still is a `Python` language runtime which we will need to change to one supporting `Ruby` as we continue in this tutorial.

## Preparing the Docker environment

Our language runtime's `Dockerfile` has the task of preparing an environment for executing OpenWhisk Actions.
Using the ActionLoop approach, we use a multistage Docker build to

1. derive our OpenWhisk language runtime from an existing Docker image that has all the target language's tools and libraries for running functions authored in that language.
    * In our case, we will reference the `ruby:2.6.2-alpine3.9` image from the [Official Docker Images for Ruby](https://hub.docker.com/_/ruby) on Docker Hub.
1. leverage the existing `openwhisk/actionlooop-v2` image on Docker Hub from which we will "extract" the *ActionLoop* proxy (i.e. copy `/bin/proxy` binary) our runtime will use to process Activation requests from the OpenWhisk platform and execute Actions by using the language's tools and libraries from step #1.

## Repurpose the renamed Python Dockerfile for Ruby builds

Let's edit the `ruby2.6/Dockerfile` to use the official Ruby image on Docker Hub as our base image, instead of a Python image, and add our our Ruby launcher script:

```dockerfile
 FROM openwhisk/actionloop-v2:latest as builder
-FROM python:3.7-alpine
+FROM ruby:2.6.2-alpine3.9
 RUN mkdir -p /proxy/bin /proxy/lib /proxy/action
 WORKDIR /proxy
 COPY --from=builder /bin/proxy /bin/proxy
-ADD lib/launcher.py /proxy/lib/launcher.py
+ADD lib/launcher.rb /proxy/lib/launcher.rb
 ADD bin/compile /proxy/bin/compile
+RUN apk update && apk add python3
 ENV OW_COMPILER=/proxy/bin/compile
 ENTRYPOINT ["/bin/proxy"]
```

Next, let's rename the `launcher.py` (a Python script) to one that indicates it is a Ruby script named `launcher.rb`.

```bash
$ mv ruby2.6/lib/launcher.py ruby2.6/lib/launcher.rb
```

Note that:

1. You changed the base Docker image to use a `Ruby` language image.
1. You changed the launcher script from `Python` to `Ruby`.
1. We had to add a `python3` package to our Ruby image since our `compile` script will be written in Python for this tutorial. Of course, you may choose to rewrite the `compile` script in `Ruby` if you wish to as your own exercise.

## Implementing the ActionLoop protocol

This section will take you through how to convert the contents of `launcher.rb` (formerly `launcher.py`) to the target Ruby programming language and implement the `ActionLoop protocol`.

### What the launcher needs to do

Let's recap the steps the launcher must accomplish to implement the `ActionLoop protocol` :

1. import the Action function's `main` method for execution.
    * Note: the `compile` script will make the function available to the launcher.
1. open the system's `file descriptor 3` which will be used to output the functions response.
1. read the system's standard input, `stdin`, line-by-line. Each line is parsed as a JSON string and produces a JSON object (not an array nor a scalar) to be passed as the input `arg` to the function.
    * Note: within the JSON object, the `value` key contains the user parameter data to be passed to your functions. All the other keys are made available as process environment variables to the function; these need to be uppercased and prefixed with `"__OW_"`.
1. invoke the `main` function with the JSON object payload.
1. encode the result of the function in JSON (ensuring it is only one line and it is terminated with one newline) and write it to `file descriptor 3`.
1. Once the function returns the result, flush the contents of `stdout`, `stderr` and `file descriptor 3` (FD 3).
1. Finally, include the above steps in a loop so that it continually looks for Activations. That's it.

### Converting launcher script to Ruby

Now, let's look at the protocol described above, codified within the launcher script `launcher.rb`, and work to convert its contents from Python to Ruby.

#### Import the function code

Skipping the first few library import statements within  `launcer.rb`, which we will have to resolve later after we determine which ones Ruby may need, we see the first significant line of code importing the actual Action function.

```python
# now import the action as process input/output
from main__ import main as main
```

In Ruby, this can be rewritten as:

```ruby
# requiring user's action code
require "./main__"
```

*Note that you are free to decide the path and filename for the function's source code. In our examples, we chose a base filename that includes the word `"main"` (since it is OpenWhisk's default function name) and append two underscores to better assure uniqueness.*

#### Open File Descriptor (FD) 3 for function results output

The `ActionLoop` proxy expects to read the results of invoking the Action function from File Descriptor (FD) 3.

The existing Python:

```python
out = fdopen(3, "wb")
```

would be rewritten in Ruby as:

```ruby
out = IO.new(3)
```

#### Process Action's arguments from STDIN

Each time the function is invoked via an HTTP request, the `ActionLoop` proxy passes the message contents to the launcher via STDIN. The launcher must read STDIN line-by-line and parse it as JSON.

The `launcher`'s existing Python code reads STDIN line-by-line as follows:

```python
while True:
  line = stdin.readline()
  if not line: break
  # ...continue...
```

would be translated to Ruby as follows:

```ruby
while true
  # JSON arguments get passed via STDIN
  line = STDIN.gets()
  break unless line
  # ...continue...
end
```

Each line is parsed in JSON, where the `payload` is extracted from contents of the `"value"` key. Other keys and their values are as uppercased, `"__OW_"` prefixed environment variables:

The existing Python code for this is:

```python
  # ... continuing ...
  args = json.loads(line)
  payload = {}
  for key in args:
    if key == "value":
      payload = args["value"]
    else:
      os.environ["__OW_%s" % key.upper()]= args[key]
  # ... continue ...
```

would be translated to Ruby:

```ruby
  # ... continuing ...
  args = JSON.parse(line)
  payload = {}
  args.each do |key, value|
    if key == "value"
      payload = value
    else
      # set environment variables for other keys
      ENV["__OW_#{key.upcase}"] = value
    end
  end
  # ... continue ...
```

#### Invoking the Action function

We are now at the point of invoking the Action function and producing its result. *Note we **must** also capture exceptions and produce an `{"error": <result> }` if anything goes wrong during execution.*

The existing Python code for this is:

```python
  # ... continuing ...
  res = {}
  try:
    res = main(payload)
  except Exception as ex:
    print(traceback.format_exc(), file=stderr)
    res = {"error": str(ex)}
  # ... continue ...
```

would be translated to Ruby:

```ruby
  # ... continuing ...
  res = {}
  begin
    res = main(payload)
  rescue Exception => e
    puts "exception: #{e}"
    res ["error"] = "#{e}"
  end
  # ... continue ...
```

#### Finalize File Descriptor (FD) 3, STDOUT and STDERR

Finally, we need to write the function's result to File Descriptor (FD) 3 and "flush" standard out (stdout), standard error (stderr) and FD 3.

The existing Python code for this is:

```python
  out.write(json.dumps(res, ensure_ascii=False).encode('utf-8'))
  out.write(b'\n')
  stdout.flush()
  stderr.flush()
  out.flush()
```

would be translated to Ruby:

```ruby
  STDOUT.flush()
  STDERR.flush()
  out.puts(res.to_json)
  out.flush()
```

Congratulations! You just completed your `ActionLoop` request handler.

## Writing the compilation script

Now, we need to write the `compilation script`. It is basically a script that will prepare the uploaded sources for execution, adding the `launcher` code and generate the final executable.

For interpreted languages, the compilation script will only "prepare" the sources for execution. The executable is simply a shell script to invoke the interpreter.

For compiled languages, like Go it will actually invoke a compiler in order to produce the final executable. There are also cases like Java where we still need to execute the compilation step that produces intermediate code, but the executable is just a shell script that will launch the Java runtime.

### How the ActionLoop proxy handles action uploads

The OpenWhisk user can upload actions with the `wsk` Command Line Interface (CLI) tool as a single file.

This single file can be:

- a source file
- an executable file
- a ZIP file containing sources
- a ZIP file containing an executable and other support files

*Important*:  an executable for ActionLoop is either a Linux binary (an ELF executable) or a script. A script is, using Linux conventions, is anything starting with `#!`. The first line is interpreted as the command to use to launch the script: `#!/bin/bash`, `#!/usr/bin/python` etc.

The ActionLoop proxy accepts any file, prepares a work folder, with two folders in it named `"src"` and `"bin"`. Then it detects the format of the uploaded file.  For each case, the behavior is different.

- If the uploaded file is an executable, it is stored as `bin/exec` and executed.
- If the uploaded file is not an executable and not a zip file, it is stored as `src/exec` then the compilation script is invoked.
- If the uploaded file is a zip file, it is unzipped in the `src` folder, then the `src/exec` file is checked.
- If it exists and it is an executable, the folder `src` is renamed to `bin` and then again the `bin/exec` is executed.
- If the `src/exec` is missing or is not an executable, then the compiler script is invoked.

### Compiling an action in source format

The compilation script is invoked only when the upload contains sources. According to the description in the past paragraph, if the upload is a single file, we can expect the file is in `src/exec`, without any prefix. Otherwise, sources are spread the `src` folder and it is the task of the compiler script to find the sources. A runtime may impose that when a zip file is uploaded, then there should be a fixed file with the main function. For example, the Python runtime expects the file `__main__.py`. However, it is not a rule: the Go runtime does not require any specific file as it compiles everything. It only requires a function with the name specified.

The compiler script goal is ultimately to leave in `bin/exec` an executable (implementing the ActionLoop protocol) that the proxy can launch. Also, if the executable is not standalone, other files must be stored in this folder, since the proxy can also zip all of them and send to the user when using the pre-compilation feature.

The compilation script is a script pointed by the `OW_COMPILER` environment variable (you may have noticed it in the Dockerfile) that will be invoked with 3 parameters:

1. `<main>` is the name of the main function specified by the user on the `wsk` command line
1. `<src>` is the absolute directory with the sources already unzipped
1.  an empty `<bin>` directory where we are expected to place our final executables

Note that both the `<src>` and `<bin>` are disposable, so we can do things like removing the `<bin>` folder and rename the `<src>`.

Since the user generally only sends a function specified by the `<main>` parameter, we have to add the launcher we wrote and adapt it to execute the function.

### Implementing the `compile` for Ruby

This is the algorithm that the `compile` script in the kit follows for Python:

1. if there is a `<src>/exec` it must rename to the main file; I use the name `main__.py`
1. if there is a `<src>/__main__.py` it will rename to the main file `main__.py`
1. copy the `launcher.py` to `exec__.py`, replacing the `main(arg)` with `<main>(arg)`;  this file imports the `main__.py` and invokes the function `<main>`
1. add a launcher script `<src>/exec`
1. finally it removes the `<bin>` folder and rename `<src>` to `<bin>`

We can adapt this algorithm easily to Ruby with just a few changes.

The script defines the functions `sources` and `build` then starts the execution, at the end of the script.

Start from the end of the script, where the script collect parameters from the command line. Instead of `launcher.py`, use `launcher.rb`:

```
- launcher = "%s/lib/launcher.py" % dirname(dirname(sys.argv[0]))
+ launcher = "%s/lib/launcher.rb" % dirname(dirname(sys.argv[0]))
```

Then the script invokes the `source` function. This function renames the `exec` file to `main__.py`, you will rename it instead to `main__.rb`:

```ruby
- copy_replace(src_file, "%s/main__.py" % src_dir)
+ copy_replace(src_file, "%s/main__.rb" % src_dir)
```

If instead there is a `__main__.py` the function will rename to `main__.py` (the launcher invokes this file always). The Ruby runtime will use a `main.rb` as starting point. So the next change is:

```ruby
- # move __main__ in the right place if it exists
- src_file = "%s/__main__.py" % src_dir
+ # move main.rb in the right place if it exists
+ src_file = "%s/main.rb" % src_dir
```

Now, the `source` function  copies the launcher as `exec__.py`, replacing the line `from main__ import main as main` (invoking the main function) with `from main__ import <main> as main`. In Ruby you may want to replace the line `res = main(payload)` with `res = <main>(payload)`. In code it is:

```ruby
- copy_replace(launcher, "%s/exec__.py" % src_dir,
-   "from main__ import main as main",
-    "from main__ import %s as main" % main )
+ copy_replace(launcher, "%s/exec__.rb" % src_dir,
+    "res = main(payload)",
+     "res = %s(payload)" % main )
```

We are almost done. We just need the startup script that instead of invoking python will invoke Ruby. So in the `build` function do this change:

```ruby
 write_file("%s/exec" % tgt_dir, """#!/bin/sh
 cd "$(dirname $0)"
-exec /usr/local/bin/python exec__.py
+exec ruby exec__.rb
 """)
```

For an interpreted language that is all. We move the `src` folder in the `bin`. For a compiled language instead, we may want to actually invoke the compiler to produce the executable.

## Debugging

Now that we have completed both the `launcher` and `compile` scripts, it is time to test them.

Here we will learn how to:

1. enter in a test environment
1. simple smoke tests to check things work
1. writing the validation tests
1. testing the image in an actual OpenWhisk environment

### Entering in the test environment

In the starter kit, there is a `Makefile` that can help with our development efforts.

We can build the Dockerfile using the provided Makefile. Since it has a reference to the image we are building, let's change it:

```bash
sed -i.bak -e 's/actionloop-demo-python-v3.7/actionloop-demo-ruby-v2.6/' ruby2.6/Makefile
```

We should be now able to build the image and enter in it with `make debug`. It will rebuild the image for us and put us into a shell so we can enter access the image environment for testing and debugging:

```bash
$ cd ruby2.6
$ make debug
# results omitted for brevity ...
```

Let's start with a couple of notes about this test environment.

First, use `--entrypoint=/bin/sh` when starting the image to have a shell available at our image entrypoint. Generally, this is true by default; however, in some stripped down base images a shell may not be available.

Second, the `/proxy` folder is mounted in our local directory, so that we can edit the `bin/compile` and the `lib/launcher.rb` using our editor outside the Docker image

*NOTE* It is not necessary to rebuild the Docker image with every change when using `make debug` since directories and environment variables used by the proxy indicate where the code outside the Docker container is located.

Once at the shell prompt that we will use for development,  we will have to start and stop the proxy. The shell will help us to inspect what happened inside the container.

### A simple smoke test

It is time to test. Let's write a very simple test first, converting the `example\hello.py` in `example\hello.rb` to appear as follows:

```ruby
def hello(args)
  name = args["name"] || "stranger"
  greeting = "Hello #{name}!"
  puts greeting
  { "greeting" => greeting }
end
```

Now change into the `ruby2.6` subdirectory of our runtime project and in one terminal type:

```bash
$ cd <projectdir>/ruby2.6
$ make debug
# results omitted for brevity ...
# (you should see a shell prompt of your image)
$ /bin/proxy -debug
2019/04/08 07:47:36 OpenWhisk ActionLoop Proxy 2: starting
```

Now the runtime is started in debug mode, listening on port 8080, and ready to accept Action deployments.

Open another terminal (while leaving the first one running the proxy) and go *into the top-level directory of our project* to test the Action by executing an `init` and then a couple of `run` requests using the `tools/invoke.py` test script.

These steps should look something like this in the second terminal:

```bash
$ cd <projectdir>
$ python tools/invoke.py init hello example/hello.rb
{"ok":true}
$ python tools/invoke.py run '{}'
{"greeting":"Hello stranger!"}
$ python tools/invoke.py run  '{"name":"Mike"}'
{"greeting":"Hello Mike!"}
```

We should also see debug output from the first terminal running the proxy (with the `debug` flag) which should have successfully processed the `init` and `run` requests above.

The proxy's debug output should appear something like:

```bin
/proxy # /bin/proxy -debug
2019/04/08 07:54:57 OpenWhisk ActionLoop Proxy 2: starting
2019/04/08 07:58:00 compiler: /proxy/bin/compile
2019/04/08 07:58:00 it is source code
2019/04/08 07:58:00 compiling: ./action/16/src/exec main: hello
2019/04/08 07:58:00 compiling: /proxy/bin/compile hello action/16/src action/16/bin
2019/04/08 07:58:00 compiler out: , <nil>
2019/04/08 07:58:00 env: [__OW_API_HOST=]
2019/04/08 07:58:00 starting ./action/16/bin/exec
2019/04/08 07:58:00 Start:
2019/04/08 07:58:00 pid: 13
2019/04/08 07:58:24 done reading 13 bytes
Hello stranger!
XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
2019/04/08 07:58:24 received::{"greeting":"Hello stranger!"}
2019/04/08 07:58:54 done reading 27 bytes
Hello Mike!
XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX
2019/04/08 07:58:54 received::{"greeting":"Hello Mike!"}
```

### Hints and tips for debugging

Of course, it is very possible something went wrong. Here a few debugging suggestions:

The ActionLoop runtime (proxy) can only be initialized once using the `init` command from the `invoke.py` script. If we need to re-initialize the runtime, we need to stop the runtime (i.e., with Control-C)  and restart it.

We can also check what is in the action folder. The proxy creates a numbered folder under `action` and then a `src` and `bin` folder.

For example, using a terminal window, we would would see a directory and file structure created by a single action:

```bash
$ find
action/
action/1
action/1/bin
action/1/bin/exec__.rb
action/1/bin/exec
action/1/bin/main__.rb
```

Note that the `exec` starter, `exec__.rb` launcher and `main__.rb` action code are have all been copied under a directory numbered`1`.

In addition, we can try to run the action directly and see if it behaves properly:

```bash
$ cd action/1/bin
$ ./exec 3>&1
$ {"value":{"name":"Mike"}}
Hello Mike!
{"greeting":"Hello Mike!"}
```

Note we redirected the file descriptor 3 in stdout to check what is happening, and note that logs appear in stdout too.

Also, we can test the compiler invoking it directly.

First let's prepare the environment as it appears when we just uploaded the action:

```bash
$ cd /proxy
$ mkdir -p action/2/src action/2/bin
$ cp action/1/bin/main__.rb action/2/src/exec
$ find action/2
action/2
action/2/bin
action/2/src
action/2/src/exec
```

Now compile and examine the results again:

```bash
$ /proxy/bin/compile main action/2/src action/2/bin
$ find action/2
action/2/
action/2/bin
action/2/bin/exec__.rb
action/2/bin/exec
action/2/bin/main__.rb
```

## Testing

If we have reached this point in the tutorial, the runtime is able to run and execute a simple test action. Now we need to validate the runtime against a set of mandatory tests both locally and within an OpenWhisk staging environment. Additionally, we should author and automate additional tests for language specific features and styles.

The `starter kit` includes two handy `makefiles` that we can leverage for some additional tests. In the next sections, we will show how to update them for testing our Ruby runtime.

### Testing multi-file Actions

So far we tested a only an Action comprised of a single file. We should also test multi-file Actions (i.e., those with relative imports) sent to the runtime in both source and binary formats.

First, let's try a multi-file Action by creating a Ruby Action script named `example/main.rb` that invokes our `hello.rb` as follows:

```ruby
require "./hello"
def main(args)
    hello(args)
end
```

Within the `example/Makefile` makefile:

- update the name of the image to `ruby-v2.6"` as well as the name of the `main` action.
- update the PREFIX with your DockerHub username.

```makefile
-IMG=actionloop-demo-python-v3.7:latest
-ACT=hello-demo-python
-PREFIX=docker.io/openwhisk
+IMG=actionloop-demo-ruby-v2.6:latest
+ACT=hello-demo-ruby
+PREFIX=docker.io/<docker username>
```

Now, we are ready to test the various cases. Again, start the runtime proxy in debug mode:

```bash
$ cd ruby2.6
$ make debug
$ /bin/proxy -debug
```

On another terminal, try to deploy a single file:

```bash
$ make test-single
python ../tools/invoke.py init hello ../example/hello.rb
{"ok":true}
python ../tools/invoke.py run '{}'
{"greeting":"Hello stranger!"}
python ../tools/invoke.py run '{"name":"Mike"}'
{"greeting":"Hello Mike!"}
```

Now, *stop and restart the proxy* and try to send a ZIP file with the sources:

```
$ make test-src-zip
zip src.zip main.rb hello.rb
  adding: main.rb (deflated 42%)
  adding: hello.rb (deflated 42%)
python ../tools/invoke.py init ../example/src.zip
{"ok":true}
python ../tools/invoke.py run '{}'
{"greeting":"Hello stranger!"}
python ../tools/invoke.py run '{"name":"Mike"}'
{"greeting":"Hello Mike!"}
```

Finally, test the pre-compilation: the runtime builds a zip file with the sources ready to be deployed. Again, *stop and restart the proxy* then:

```
$ make test-bin-zip
docker run -i actionloop-demo-ruby-v2.6:latest -compile main <src.zip >bin.zip
python ../tools/invoke.py init ../example/bin.zip
{"ok":true}

python ../tools/invoke.py run '{}'
{"greeting":"Hello stranger!"}

python ../tools/invoke.py run '{"name":"Mike"}'
{"greeting":"Hello Mike!"}
```

Congratulations! The runtime works locally! Time to test it on the public cloud. So as the last step before moving forward, let's push the image to Docker Hub with `make push`.

### Testing on OpenWhisk

To run this test you need to configure access to OpenWhisk with `wsk`. A simple way is to get access is to register a free account in the IBM Cloud but this works also with our own deployment of OpenWhisk.

Edit the Makefile as we did previously:

```makefile
IMG=actionloop-demo-ruby-v2.6:latest
ACT=hello-demo-ruby
PREFIX=docker.io/<docker username>
```

Also, change any reference to `hello.py` and `main.py` to `hello.rb` and `main.rb`.

Once this is done, we can re-run the tests we executed locally on "the real thing".

Test single:

```bash
$ make test-single
wsk action update hello-demo-ruby hello.rb --docker docker.io/linus/actionloop-demo-ruby-v2.6:latest --main hello
ok: updated action hello-demo-ruby
wsk action invoke hello-demo-ruby -r
{
    "greeting": "Hello stranger!"
}
wsk action invoke hello-demo-ruby -p name Mike -r
{
    "greeting": "Hello Mike!"
}
```

Test source zip:

```bash
$ make test-src-zip
zip src.zip main.rb hello.rb
  adding: main.rb (deflated 42%)
  adding: hello.rb (deflated 42%)
wsk action update hello-demo-ruby src.zip --docker docker.io/linus/actionloop-demo-ruby-v2.6:latest
ok: updated action hello-demo-ruby
wsk action invoke hello-demo-ruby -r
{
    "greeting": "Hello stranger!"
}
wsk action invoke hello-demo-ruby -p name Mike -r
{
    "greeting": "Hello Mike!"
}
```

Test binary ZIP:

```bash
$ make test-bin-zip
docker run -i actionloop-demo-ruby-v2.6:latest -compile main <src.zip >bin.zip
wsk action update hello-demo-ruby bin.zip --docker docker.io/actionloop/actionloop-demo-ruby-v2.6:latest
ok: updated action hello-demo-ruby
wsk action invoke hello-demo-ruby -r
{
    "greeting": "Hello stranger!"
}
wsk action invoke hello-demo-ruby -p name Mike -r
{
    "greeting": "Hello Mike!"
}
```

Congratulations! Your runtime works also in the real world.

### Writing the validation tests

Before you can submit your runtime you should ensure your runtime pass the validation tests.

Under `tests/src/test/scala/runtime/actionContainers/ActionLoopPythonBasicTests.scala` there is the template for the test.

Rename to `tests/src/test/scala/runtime/actionContainers/ActionLoopRubyBasicTests.scala`, change internally the class name to `class ActionLoopRubyBasicTests` and implement the following test cases:

- `testNotReturningJson`
- `testUnicode`
- `testEnv`
- `testInitCannotBeCalledMoreThanOnce`
- `testEntryPointOtherThanMain`
- `testLargeInput`

You should convert Python code to Ruby code. We do not do go into the details of each test, as they are pretty simple and obvious. You can check the source code for the real test [here](https://github.com/apache/incubator-openwhisk-runtime-ruby/blob/master/tests/src/test/scala/actionContainers/Ruby26ActionLoopContainerTests.scala).

You can verify tests are running properly with:

```bash
$ ./gradlew test

Starting a Gradle Daemon, 1 busy Daemon could not be reused, use --status for details

> Task :tests:test

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should handle initialization with no code PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should handle initialization with no content PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should run and report an error for function not returning a json object PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should fail to initialize a second time PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should invoke non-standard entry point PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should echo arguments and print message to stdout/stderr PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should handle unicode in source, input params, logs, and result PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should confirm expected environment variables PASSED

runtime.actionContainers.ActionLoopPythoRubyTests > runtime proxy should echo a large input PASSED

BUILD SUCCESSFUL in 55s
```

Big congratulations are in order having reached this point successfully. At this point, our runtime should be ready to run on any OpenWhisk platform and also can be submitted for consideration to be included in the Apache OpenWhisk project.


text:
/**
 * Date: 8/6/13
 * Time: 11:44 AM
 */

package org.wso2.carbon.bam.jmx.agent.exceptions;

public class JmxProfileException extends Exception {

    private static final long serialVersionUID = 1964250880783971787L;

    private String message;

    public String getMessage() {
        return message;
    }

    public JmxProfileException(String message) {
        this.message = message;
    }

    public JmxProfileException(String message, Throwable cause) {
        super(message, cause);
        this.message = message;
    }
}

redpajama_set_name: RedPajamaGithub


text:
from __future__ import division
__doc__="""
Inserts instances, based on the Luc(as), Pablo, and Maciej algorithms.
"""
import vanilla
import GlyphsApp

rangemin = 3
rangemax = 11

def distribute_lucas( min, max, n ):
	q = max / min
	return [ min * q**(i/(n-1)) for i in range(n) ]

def distribute_equal( min, max, n ):
	d = (max - min) / (n-1)
	return [ min + i*d for i in range(n) ]

def distribute_pablo( min, max, n ):
	es = distribute_equal(min, max, n)
	ls = distribute_lucas(min, max, n)
	return [ l*(1-i/(n-1)) + e*(i/(n-1)) for (i, e, l) in zip(range(n), es, ls) ]

def distribute_maciej( lightMasterWeightX, lightMasterWeightY, boldMasterWeightX, boldMasterWeightY, interpolationWeightX ):
	"""
	Algorithm by Maciej Ratajski
	http://jsfiddle.net/Dm2Zk/1/
	"""
	interpolationPointX =  ( interpolationWeightX - lightMasterWeightX ) / ( boldMasterWeightX - lightMasterWeightX )
	interpolationWeightY = ( ( 1 - interpolationPointX ) * ( lightMasterWeightY / lightMasterWeightX - boldMasterWeightY / boldMasterWeightX ) + boldMasterWeightY / boldMasterWeightX ) * interpolationWeightX
	interpolationPointY =  ( interpolationWeightY - lightMasterWeightY) / ( boldMasterWeightY - lightMasterWeightY )

	return round( ( boldMasterWeightX - lightMasterWeightX ) * interpolationPointY + lightMasterWeightX, 1 )

class InstanceMaker( object ):
	"""GUI for injecting instances."""
	def __init__( self ):
		self.w = vanilla.FloatingWindow( (360, 350), "Insert weight instances", minSize=(360, 350), maxSize=(360, 500), autosaveName="com.mekkablue.InstanceMaker.mainwindow" )

		self.w.text_1 = vanilla.TextBox( (15-1, 12+2, 75, 14), "Insert", sizeStyle='small' )
		self.w.numberOfInstances = vanilla.PopUpButton( (15+40, 12, 50, 17), [str(x) for x in range( 3, 12 )], callback=self.UpdateSample, sizeStyle='small' )
		self.w.text_2 = vanilla.TextBox( (15+40+55, 12+2, 120, 14), "instances with prefix", sizeStyle='small' )
		self.w.prefix = vanilla.EditText( (15+40+55+120, 12-1, -15, 19), "A-", callback=self.UpdateSample, sizeStyle='small')

		self.w.text_3 =  vanilla.TextBox( (15-1, 40+2, 60, 14), "from:", sizeStyle='small')
		self.w.master1 = vanilla.ComboBox((15+40, 40-1, 50, 19), self.MasterList(1), callback=self.UpdateSample, sizeStyle='small' )
		self.w.text_4 =  vanilla.TextBox( (15+40+55, 40+2, 55, 14), "through:", sizeStyle='small')
		self.w.master2 = vanilla.ComboBox((15+40+55+55, 40-1, 50, 19), self.MasterList(-1), callback=self.UpdateSample, sizeStyle='small' )
		self.w.text_5 =  vanilla.TextBox( (15+40+55+55+55, 40+2, 55, 14), "at width:", sizeStyle='small')
		self.w.width =   vanilla.EditText((15+40+45+55+55+65, 40-1, -15, 19), "100", callback=self.SavePreferences, sizeStyle='small')

		self.w.text_6 = vanilla.TextBox( (15-1, 68+2, 60, 14), "using", sizeStyle='small')
		self.w.algorithm = vanilla.PopUpButton((15+40, 68, 80, 17), [ "Pablo", "Luc(as)", "linear" ], callback=self.UpdateSample, sizeStyle='small' )
		self.w.text_7 = vanilla.TextBox( (15+40+85, 68+2, 110, 14), "distribution:", sizeStyle='small')
		self.w.help_instances = vanilla.HelpButton((-15-21, 68+2, -15, 20), callback=self.openURL )

		self.w.existingInstances = vanilla.RadioGroup((15+30, 100, -10, 60), [ "Leave existing instances as they are", "Deactivate existing instances", "Delete existing instances" ], callback=self.SavePreferences, sizeStyle = 'small' )
		self.w.existingInstances.set( 0 )

		self.w.maciej        = vanilla.CheckBox((15, 170, 160, 19), "Maciej y distribution from:", value=False, callback=self.UpdateSample, sizeStyle='small' )
		self.w.maciej_light  = vanilla.ComboBox((15+165, 170-2, 50, 19), self.MasterList(1), callback=self.UpdateSample, sizeStyle='small' )
		self.w.text_maciej_1 = vanilla.TextBox( (15+165+55, 170+2, 55, 19), "through:", sizeStyle='small')
		self.w.maciej_bold   = vanilla.ComboBox((15+165+55+55, 170-2, -15, 19), self.MasterList(-1), callback=self.UpdateSample, sizeStyle='small' )
		self.w.text_maciej_2 = vanilla.TextBox( (15+15, 170+2+20, -40, 40), "Provide horizontal stem widths in extreme masters to interpolate contrast rather than stems.", sizeStyle='small', selectable=True )
		self.w.help_maciej   = vanilla.HelpButton((-15-21, 170+6+20, -15, 20), callback=self.openURL )

		self.w.sample = vanilla.Box( (15, 170+30+40, -15, -30-15) )
		self.w.sample.text = vanilla.TextBox( (5, 5, -5, -5), "", sizeStyle='small')

		self.w.createButton = vanilla.Button((-80-15, -20-15, -15, -15), "Create", sizeStyle='regular', callback=self.CreateInstances )
		self.w.setDefaultButton( self.w.createButton )

		if not self.LoadPreferences():
			print "Error: Could not load preferences. Will resort to defaults."

		self.w.open()
		self.UpdateSample( self )
		self.w.makeKey()

	def MasterList( self, factor ):
		Font = Glyphs.font
		MasterValues = sorted( [m.weightValue for m in Font.masters], key=lambda m: m * factor )
		return MasterValues

	def Distribution( self ):
		a = self.w.master1.get().floatValue()
		b = self.w.master2.get().floatValue()
		n = int( self.w.numberOfInstances.getItems()[self.w.numberOfInstances.get()] )

		algorithm = self.w.algorithm.getItems()[self.w.algorithm.get()]
		if algorithm == "Pablo":
			distributedValues = distribute_pablo( a, b, n )
		elif algorithm == "Luc(as)":
			distributedValues = distribute_lucas( a, b, n )
		else:
			distributedValues = distribute_equal( a, b, n )

		return distributedValues

	def UpdateSample( self, sender ):
		try:
			distributedValues = self.Distribution()
			n = len( distributedValues )
			prefix = self.w.prefix.get()
			sampleText = "Will create %i instances: %s" % ( n, ", ".join( prefix+"{0:.0f}".format(weight) for weight in distributedValues ))

			if self.w.algorithm.getItems()[self.w.algorithm.get()] == "Luc(as)":
				sampleText += ", growth: %.1f%%" % ( (distributedValues[1] / distributedValues[0]) *100-100 )

			if self.w.maciej.get():
				maciejValues = self.MaciejValues( distributedValues )
				maciejList = [ str( int( round( distribute_maciej( maciejValues[0], maciejValues[1], maciejValues[2], maciejValues[3], w)))) for w in distributedValues ]
				sampleText += "\n\nWill add interpolationWeightY parameters to the respective instances: %s" % ( ", ".join( maciejList ) + "." )

			self.w.sample.text.set( sampleText )
			self.SavePreferences( self )
		except Exception, e:
			print e

	def DealWithExistingInstances( self ):
		instancesChoice = self.w.existingInstances.get()

		if instancesChoice == 1: # deactivate
			for thisInstance in Glyphs.font.instances:
				thisInstance.active = False
		elif instancesChoice == 2: # delete
			while len( Glyphs.font.instances ) != 0:
				Glyphs.font.removeInstanceAtIndex_(0)

		return True

	def SavePreferences( self, sender ):
		Glyphs.defaults["com.mekkablue.InstanceMaker.numberOfInstances"] = self.w.numberOfInstances.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.prefix"] = self.w.prefix.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.master1"] = self.w.master1.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.master2"] = self.w.master2.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.width"] = self.w.width.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.algorithm"] = self.w.algorithm.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.existingInstances"] = self.w.existingInstances.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.maciej"] = self.w.maciej.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.maciej1"] = self.w.maciej_light.get()
		Glyphs.defaults["com.mekkablue.InstanceMaker.maciej2"] = self.w.maciej_bold.get()

		return True

	def LoadPreferences( self ):
		try:
			NSUserDefaults.standardUserDefaults().registerDefaults_(
				{
					"com.mekkablue.InstanceMaker.numberOfInstances": "6",
					"com.mekkablue.InstanceMaker.prefix": "A-",
					"com.mekkablue.InstanceMaker.master1": self.MasterList(1),
					"com.mekkablue.InstanceMaker.master2": self.MasterList(-1),
					"com.mekkablue.InstanceMaker.width": "100",
					"com.mekkablue.InstanceMaker.algorithm": "0",
					"com.mekkablue.InstanceMaker.existingInstances": "0",
					"com.mekkablue.InstanceMaker.maciej": "0",
					"com.mekkablue.InstanceMaker.maciej1": self.MasterList(1),
					"com.mekkablue.InstanceMaker.maciej2": self.MasterList(-1)
				}
			)
			self.w.numberOfInstances.set( Glyphs.defaults["com.mekkablue.InstanceMaker.numberOfInstances"] )
			self.w.prefix.set( Glyphs.defaults["com.mekkablue.InstanceMaker.prefix"] )
			self.w.master1.set( Glyphs.defaults["com.mekkablue.InstanceMaker.master1"] )
			self.w.master2.set( Glyphs.defaults["com.mekkablue.InstanceMaker.master2"] )
			self.w.width.set( Glyphs.defaults["com.mekkablue.InstanceMaker.width"] )
			self.w.algorithm.set( Glyphs.defaults["com.mekkablue.InstanceMaker.algorithm"] )
			self.w.existingInstances.set( Glyphs.defaults["com.mekkablue.InstanceMaker.existingInstances"] )
			self.w.maciej.set( Glyphs.defaults["com.mekkablue.InstanceMaker.maciej"] )
			self.w.maciej_light.set( Glyphs.defaults["com.mekkablue.InstanceMaker.maciej1"] )
			self.w.maciej_bold.set( Glyphs.defaults["com.mekkablue.InstanceMaker.maciej2"] )
		except:
			return False

		return True

	def openURL( self, sender ):
		URL = None
		if sender == self.w.help_instances:
			URL = "http://www.glyphsapp.com/tutorials/multiple-masters-part-3-setting-up-instances"
		if sender == self.w.help_maciej:
			URL = "http://www.maciejratajski.com/theory/interpolation-of-contrast/"
		if URL:
			import webbrowser
			webbrowser.open( URL )

	def MaciejValues( self, distributedValues ):
		lightX = self.w.master1.get().floatValue()
		boldX  = self.w.master2.get().floatValue()
		lightY = self.w.maciej_light.get().floatValue()
		boldY  = self.w.maciej_bold.get().floatValue()
		return [ lightX, lightY, boldX, boldY ]

	def CreateInstances( self, sender ):
		try:
			if self.DealWithExistingInstances():
				distributedValues = self.Distribution()
				widthValue = self.w.width.get().floatValue()
				prefix = self.w.prefix.get()
				maciejYesOrNo = self.w.maciej.get()

				if maciejYesOrNo:
					maciejValues = self.MaciejValues( distributedValues )

				for thisWeight in distributedValues:
					newInstance = GSInstance()
					newInstance.active = True
					newInstance.name = prefix + "{0:.0f}".format( thisWeight )
					newInstance.weightValue = thisWeight
					newInstance.widthValue = widthValue
					newInstance.isItalic = False
					newInstance.isBold = False

					if maciejYesOrNo:
						interpolationY = distribute_maciej( maciejValues[0], maciejValues[1], maciejValues[2], maciejValues[3], float( thisWeight ) )
						newInstance.setCustomParameter_forKey_( int( round( interpolationY )), "InterpolationWeightY")

					Glyphs.font.addInstance_( newInstance )
					newInstance.updateInterpolationValues()

			if not self.SavePreferences( self ):
				print "Error writing preferences."

			self.w.close()
		except Exception, e:
			raise e

InstanceMaker()


text:
namespace _03.MirrorImage
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public class Program
    {
        public static void Main()
        {
            List<string> elements = Console.ReadLine().Split().ToList();
            string line = Console.ReadLine();

            while (line != "Print")
            {
                int n = int.Parse(line);
                int left = elements.Count - n;
                List<string> leftSide = new List<string>();
                List<string> rightSide = new List<string>();
                string elementN = elements[n];

                if (n != 0 && n!= elements.Count - 1)
                {
                    for (int i = 0; i < n; i++)
                    {
                        leftSide.Add(elements[i]);
                    }
                    for (int i = n + 1; i < elements.Count; i++)
                    {
                        rightSide.Add(elements[i]);
                    }

                    leftSide.Reverse();
                    rightSide.Reverse();

                    elements.Clear();
                    elements.AddRange(leftSide);
                    elements.Add(elementN);
                    elements.AddRange(rightSide);

                }
                else if (n == 0)
                {
                    rightSide.AddRange(elements);
                    rightSide.RemoveAt(0);
                    rightSide.Reverse();
                    elements.Clear();
                    elements.Add(elementN);
                    elements.AddRange(rightSide);
                }
                else // if (n == elements.Count - 1)
                {
                    leftSide.AddRange(elements);
                    leftSide.RemoveAt(elements.Count - 1);
                    leftSide.Reverse();
                    elements.Clear();
                    elements.AddRange(leftSide);
                    elements.Add(elementN);
                }

                line = Console.ReadLine();
            }

            Console.WriteLine(string.Join(" ", elements));
        }
    }
}


text:
NRUNS=1         # Reduced for sake of running time.
MYJAVAPATH="../../"

topology=XP	# JF = JellyFish,
			# FT = fat-tree,
			# XP = Xpander

patheval=SLACK	# SLACK = Use slack such that flow cannot deviate more than SLACK from shortest path src-dst
				# NEIGH = Use neighbor's shortest path to destination
				# KSHRT = Use K-shortest path

linkFailRate=0
numsvr=0
switches=231
svrports=10
netports=10
totport=`expr $svrports + $netports`
portus=`expr $netports + 1`

tmode=MAWP	# RPP = Rand. Permutation Pairs,
			# ATA = All-to-All,
			# AT1 = All-to-One,
			# STR = Stride,
			# MIWP = Min. Weight Pairs
			# MAWP = Max. Weight Pairs

for slack in 0 1 2 3 4 -1
do

	for trafficFrac in 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
	do

		# Clock start
		before="$(date +%s)"

		# Executing NRUNS times, store each resulting flow into flowtmp_slack_mawp
		rm -rf flowtmp_slack_mawp
		seed=1
		for (( i=0 ; i < $NRUNS ; i++ ))
		do
				cd $MYJAVAPATH
				echo "Testing traffic fraction $trafficFrac"
				echo "-gt $topology -tm $tmode -tfr $trafficFrac -lfr $linkFailRate -switches $switches -switchports $portus -netports $netports -servers $numsvr"
				java -jar TSim.jar -gt $topology -tm $tmode -pe $patheval -slk $slack -tfr $trafficFrac -lfr $linkFailRate -seed $seed -switches $switches -switchports $portus -netports $netports # -servers $numsvr
				sh scripts/remoteLpRun.sh
				java -jar AnalyzeTSim.jar -tm $tmode
				cd -

				flowVal=$(cat ../../temp/final/objective.txt)
				echo "$flowVal" >> flowtmp_slack_mawp
				seed=`expr $seed + 1`
		done

		# Clock end
		after="$(date +%s)"
		time_taken=`expr $after - $before`
		time_taken=`expr $time_taken / 60`

		# Calculate average and standard deviation
		avgstdflow=`cat flowtmp_slack_mawp | awk 'BEGIN{sum=0; count=0}{thr=$1; sum+=thr; val[count]=thr; count++}END{mean=sum/count; sq_sum=0; for (i=0; i < count; i++) sq_sum+=(val[i] - mean)*(val[i] - mean); variance=sqrt(sq_sum/count)/mean; rnd_mean=int(mean * 100000) / 100000; rnd_variance=int(variance*100000)/100000; print rnd_mean, rnd_variance}'`

		# Echo result
		echo "$patheval $slack $topology $switches $totport $netports $svrports $tmode $trafficFrac $avgstdflow $time_taken" >> ../../results/patheval/slack_comparison_mawp_single.txt

	done

done


text:
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Security;
using Umbraco.Extensions;

namespace Umbraco.Cms.Web.BackOffice.Security;

/// <summary>
///     Used to validate a cookie against a user's session id
/// </summary>
/// <remarks>
///     <para>
///         This uses another cookie to track the last checked time which is done for a few reasons:
///         * We can't use the user's auth ticket to do this because we'd be re-issuing the auth ticket all of the time and
///         it would never expire
///         plus the auth ticket size is much larger than this small value
///         * This will execute quite often (every minute per user) and in some cases there might be several requests that
///         end up re-issuing the cookie so the cookie value should be small
///         * We want to avoid the user lookup if it's not required so that will only happen when the time diff is great
///         enough in the cookie
///     </para>
///     <para>
///         This is a scoped/request based object.
///     </para>
/// </remarks>
public class BackOfficeSessionIdValidator
{
    public const string CookieName = "UMB_UCONTEXT_C";
    private readonly GlobalSettings _globalSettings;
    private readonly ISystemClock _systemClock;
    private readonly IBackOfficeUserManager _userManager;

    /// <summary>
    ///     Initializes a new instance of the <see cref="BackOfficeSessionIdValidator" /> class.
    /// </summary>
    public BackOfficeSessionIdValidator(ISystemClock systemClock, IOptionsSnapshot<GlobalSettings> globalSettings, IBackOfficeUserManager userManager)
    {
        _systemClock = systemClock;
        _globalSettings = globalSettings.Value;
        _userManager = userManager;
    }

    public async Task ValidateSessionAsync(TimeSpan validateInterval, CookieValidatePrincipalContext context)
    {
        if (!context.Request.IsBackOfficeRequest())
        {
            return;
        }

        var valid = await ValidateSessionAsync(validateInterval, context.HttpContext, context.Options.CookieManager, _systemClock, context.Properties.IssuedUtc, context.Principal?.Identity as ClaimsIdentity);

        if (valid == false)
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(Constants.Security.BackOfficeAuthenticationType);
        }
    }

    private async Task<bool> ValidateSessionAsync(
        TimeSpan validateInterval,
        HttpContext httpContext,
        ICookieManager cookieManager,
        ISystemClock systemClock,
        DateTimeOffset? authTicketIssueDate,
        ClaimsIdentity? currentIdentity)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }

        if (cookieManager == null)
        {
            throw new ArgumentNullException(nameof(cookieManager));
        }

        if (systemClock == null)
        {
            throw new ArgumentNullException(nameof(systemClock));
        }

        if (currentIdentity == null)
        {
            return false;
        }

        DateTimeOffset? issuedUtc = null;
        DateTimeOffset currentUtc = systemClock.UtcNow;

        // read the last checked time from a custom cookie
        var lastCheckedCookie = cookieManager.GetRequestCookie(httpContext, CookieName);

        if (lastCheckedCookie.IsNullOrWhiteSpace() == false)
        {
            if (DateTimeOffset.TryParse(lastCheckedCookie, out DateTimeOffset parsed))
            {
                issuedUtc = parsed;
            }
        }

        // no cookie, use the issue time of the auth ticket
        if (issuedUtc.HasValue == false)
        {
            issuedUtc = authTicketIssueDate;
        }

        // Only validate if enough time has elapsed
        var validate = issuedUtc.HasValue == false;
        if (issuedUtc.HasValue)
        {
            TimeSpan timeElapsed = currentUtc.Subtract(issuedUtc.Value);
            validate = timeElapsed > validateInterval;
        }

        if (validate == false)
        {
            return true;
        }

        var userId = currentIdentity.GetUserId();
        if (userId is null)
        {
            return false;
        }

        var user = await _userManager.FindByIdAsync(userId);
        if (user == null)
        {
            return false;
        }

        var sessionId = currentIdentity.FindFirstValue(Constants.Security.SessionIdClaimType);
        if (await _userManager.ValidateSessionIdAsync(userId, sessionId) == false)
        {
            return false;
        }

        // we will re-issue the cookie last checked cookie
        cookieManager.AppendResponseCookie(
            httpContext,
            CookieName,
            DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz"),
            new CookieOptions
            {
                HttpOnly = true,
                Secure = _globalSettings.UseHttps || httpContext.Request.IsHttps,
                Path = "/"
            });

        return true;
    }
}


text:
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace OmniSharp.Intellisense
{
    internal class NamespaceKeywordRecommender : AbstractSyntacticSingleKeywordRecommender
    {
        public NamespaceKeywordRecommender()
            : base(SyntaxKind.NamespaceKeyword)
        {
        }

        protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken)
        {
            var syntaxTree = context.SyntaxTree;

            // namespaces are illegal in interactive code:
            if (syntaxTree.IsInteractiveOrScript())
            {
                return false;
            }

            // cases:
            // root: |

            // root: n|

            // extern alias a;
            // |

            // extern alias a;
            // n|

            // using Foo;
            // |

            // using Foo;
            // n|

            // using Foo = Bar;
            // |

            // using Foo = Bar;
            // n|

            // namespace N {}
            // |

            // namespace N {}
            // n|

            // class C {}
            // |

            // class C {}
            // n|

            var leftToken = context.LeftToken;
            var token = context.TargetToken;

            // root: n|

            // ns Foo { n|

            // extern alias a;
            // n|

            // using Foo;
            // n|

            // using Foo = Bar;
            // n|

            // a namespace can't come before usings/externs
            // a child namespace can't come before usings/externs
            if (leftToken.GetNextToken(includeSkipped: true).IsUsingOrExternKeyword())
            {
                return false;
            }

            // root: |
            if (token.Kind() == SyntaxKind.None)
            {
                // root namespace
                var root = syntaxTree.GetRoot(cancellationToken) as CompilationUnitSyntax;
                if (root.Externs.Count > 0 ||
                    root.Usings.Count > 0)
                {
                    return false;
                }

                return true;
            }

            if (token.Kind() == SyntaxKind.OpenBraceToken &&
                token.Parent.IsKind(SyntaxKind.NamespaceDeclaration))
            {
                return true;
            }

            // extern alias a;
            // |

            // using Foo;
            // |
            if (token.Kind() == SyntaxKind.SemicolonToken)
            {
                if (token.Parent.IsKind(SyntaxKind.ExternAliasDirective, SyntaxKind.UsingDirective))
                {
                    return true;
                }
            }

            // class C {}
            // |
            if (token.Kind() == SyntaxKind.CloseBraceToken)
            {
                if (token.Parent is TypeDeclarationSyntax &&
                    !(token.Parent.GetParent() is TypeDeclarationSyntax))
                {
                    return true;
                }
                else if (token.Parent.IsKind(SyntaxKind.NamespaceDeclaration))
                {
                    return true;
                }
            }

            // delegate void D();
            // |

            if (token.Kind() == SyntaxKind.SemicolonToken)
            {
                if (token.Parent.IsKind(SyntaxKind.DelegateDeclaration) &&
                    !(token.Parent.GetParent() is TypeDeclarationSyntax))
                {
                    return true;
                }
            }

            // [assembly: foo]
            // |

            if (token.Kind() == SyntaxKind.CloseBracketToken &&
                token.Parent.IsKind(SyntaxKind.AttributeList) &&
                token.Parent.IsParentKind(SyntaxKind.CompilationUnit))
            {
                return true;
            }

            return false;
        }
    }
}


text:
require 'spec_helper'

describe ShopImage do
  describe 'schema' do
    it { expect(subject).to have_db_column(:subject_id).of_type(:integer) }
    it { expect(subject).to have_db_column(:subject_type).of_type(:string) }
    it { expect(subject).to have_db_column(:image).of_type(:string) }
    it { expect(subject).to have_db_column(:created_at) }
    it { expect(subject).to have_db_column(:updated_at) }
  end
end


text:
{% extends "dashboard/base.html" %}
{% load i18n %}
{% load prices_i18n %}
{% load status %}

{% block title %}{% trans "Orders" %} - {{ block.super }}{% endblock %}

{% block content %}

{% trans "Orders" %}

            {% include "dashboard/includes/_status_filters.html" %}
            {% include "dashboard/includes/_orders_table.html" with orders=object_list %}
            {% include "dashboard/includes/_pagination.html" %}

{% endblock %}


text:
function FS(){
    return new ActiveXObject("Scripting.FileSystemObject");
}

function readFile(f) {
    return FS().OpenTextFile(f,1).ReadAll();
}

eval(readFile("lib\\includelib.js"));
include("lib\\json3.min.js");
include("lib\\underscore-min.js");
include("lib\\msgbox.js");

var MSCONST = (function () {
    var stuff = {
        ppLayoutBlank     : 12,
        ppLayoutTitle     : 1,
        ppLayoutTitleOnly : 11,
        msoLineSingle     : 1,
        msoFalse          : 0,
        msoTrue           : -1
    };

    return {
        get: function(name) { return stuff[name]; }
    };

})();

function addBorder(pic){
    pic.Line.Weight = 0.25;
    pic.Line.Style = MSCONST.get('msoLineSingle');
}

function setMargin(pictureUnits,availableUnits,marginEdge,slideUnits){
    var margin = 0;
    if(pictureUnits > availableUnits) {
        margin = marginEdge;
    }
    else {
        var a  = (slideUnits - marginEdge) / 2;
        var b  = slideUnits - a;
        var c  = pictureUnits / 2;
        margin = b - c;
    }
    return margin;
}

function center(pic,slide,sHeight,sWidth){
    var pHeight     = pic.Height;
    var pWidth      = pic.Width;
    var title       = slide.Shapes.title;
    var tHeight     = title.Height;
    var tTop        = title.Top;
    var tBottom     = tHeight + tTop;
    var tLeft       = title.Left;
    var tWidth      = title.Width;
    //var tRight      = tLeft + tWidth;

    // Available Height
    var aHeight     = sHeight - tBottom - 1;
    var aHeight_Top = sHeight - aHeight;

    pic.Top  = setMargin(pHeight,aHeight,aHeight_Top,sHeight);
    pic.Left = setMargin(pWidth,sWidth,0,sWidth);
}

function addSlide(ppt){
    var newSlidePosition = ppt.Slides.Count + 1;
    var slide = ppt.Slides.Add(newSlidePosition,MSCONST.get('ppLayoutTitleOnly'));
    return slide;
}

function insertPic(pic,slide) {
    var s                = slide.Shapes;
    var linkToFile       = MSCONST.get('msoFalse');
    var saveWithDocument = MSCONST.get('msoTrue');
    var left             = 0;
    var top              = 0;
    var picOnSlide       = s.AddPicture( pic, linkToFile, saveWithDocument, left, top );
    return picOnSlide;
}

function initConfig(){
    var s = readFile("settings.json");
    var config = JSON.parse(s);

    var fixPath = function(s){
    var re = /\|/gi;
    return s.replace(re,'\\');
    }

    config.fullPath = fixPath(config.fullPath);
    config.projectPath = config.fullPath + "\\" + config.projectName;
    config.tmp = config.projectPath + "\\tmp"
    config.tmpDoc = config.tmp + "\\tmp.docx";
    config.tmpPicName = "image1.png";
    config.tmpPicPath = config.tmp + "\\" + config.tmpPicName;
    config.pixPath = config.projectPath + "\\screenshots";
    config.report = config.projectPath + "\\report.json";
    config.cwd = new ActiveXObject("WScript.Shell").CurrentDirectory;
    config.bin = config.cwd + "\\bin";
    return config;
}

function insertTitle(text,slide) {
    slide.Shapes.Title.TextFrame.TextRange.Text = text;
}

function png2ppt(){
    var powerpnt     = new ActiveXObject("PowerPoint.Application")
    powerpnt.Visible = true;
    var ppt          = powerpnt.Presentations.Add();
    var sHeight      = ppt.PageSetup.SlideHeight;
    var sWidth       = ppt.PageSetup.SlideWidth;
    var config       = initConfig();
    var s            = readFile(config.report);
    var report       = JSON.parse(s);

    var i = new Enumerator(report);
    while (!i.atEnd()) {
        var note = i.item();
        var slide = addSlide(ppt);
        var fileName = config.pixPath + "\\" + note.screenshot;
        var title = note.caption;
        insertTitle(note.caption,slide);
        var pic = insertPic(fileName,slide)
        addBorder(pic);
        center(pic,slide,sHeight,sWidth);
        i.moveNext();
    }

}

function main() {
    png2ppt();
}

main();


text:
using System;

namespace BTDB.Allocators
{
    public interface IOffHeapAllocator
    {
        IntPtr Allocate(IntPtr size);
        void Deallocate(IntPtr ptr);
    }
}


text:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RecordWildCards  #-}
{-# LANGUAGE TemplateHaskell, OverloadedStrings #-}
module Stack.NixSpec where

import Control.Exception
import Control.Monad.Logger
import Data.Maybe
import Data.Monoid
import Options.Applicative
import Path
import Prelude -- to remove the warning about Data.Monoid being redundant on GHC 7.10
import Stack.Config
import Stack.Options.NixParser
import Stack.Config.Nix
import Stack.Types.Compiler
import Stack.Types.Config
import Stack.Types.Nix
import Stack.Types.StackT
import Stack.Types.Version
import System.Directory
import System.Environment
import System.IO.Temp (withSystemTempDirectory)
import Test.Hspec

sampleConfigNixEnabled :: String
sampleConfigNixEnabled =
  "resolver: lts-2.10\n" ++
  "packages: ['.']\n" ++
  "system-ghc: true\n" ++
  "nix:\n" ++
  "   enable: True\n" ++
  "   packages: [glpk]"

sampleConfigNixDisabled :: String
sampleConfigNixDisabled =
  "resolver: lts-2.10\n" ++
  "packages: ['.']\n" ++
  "nix:\n" ++
  "   enable: False"

stackDotYaml :: Path Rel File
stackDotYaml = $(mkRelFile "stack.yaml")

setup :: IO ()
setup = unsetEnv "STACK_YAML"

spec :: Spec
spec = beforeAll setup $ do
  let loadConfig' cmdLineArgs = runStackT () LevelDebug True False ColorAuto False (loadConfig cmdLineArgs Nothing Nothing)
      inTempDir test = do
        currentDirectory <- getCurrentDirectory
        withSystemTempDirectory "Stack_ConfigSpec" $ \tempDir -> do
          let enterDir = setCurrentDirectory tempDir
              exitDir = setCurrentDirectory currentDirectory
          bracket_ enterDir exitDir test
      withStackDotYaml config test = inTempDir $ do
        writeFile (toFilePath stackDotYaml) config
        test
      parseNixOpts cmdLineOpts = fromJust $ getParseResult $ execParserPure
        defaultPrefs
        (info (nixOptsParser False) mempty)
        cmdLineOpts
      parseOpts cmdLineOpts = mempty { configMonoidNixOpts = parseNixOpts cmdLineOpts }
  describe "nix disabled in config file" $
    around_ (withStackDotYaml sampleConfigNixDisabled) $ do
      it "sees that the nix shell is not enabled" $ do
        lc <- loadConfig' mempty
        nixEnable (configNix $ lcConfig lc) `shouldBe` False
      describe "--nix given on command line" $
        it "sees that the nix shell is enabled" $ do
          lc <- loadConfig' (parseOpts ["--nix"])
          nixEnable (configNix $ lcConfig lc) `shouldBe` True
      describe "--nix-pure given on command line" $
        it "sees that the nix shell is enabled" $ do
          lc <- loadConfig' (parseOpts ["--nix-pure"])
          nixEnable (configNix $ lcConfig lc) `shouldBe` True
      describe "--no-nix given on command line" $
        it "sees that the nix shell is not enabled" $ do
          lc <- loadConfig' (parseOpts ["--no-nix"])
          nixEnable (configNix $ lcConfig lc) `shouldBe` False
      describe "--no-nix-pure given on command line" $
        it "sees that the nix shell is not enabled" $ do
          lc <- loadConfig' (parseOpts ["--no-nix-pure"])
          nixEnable (configNix $ lcConfig lc) `shouldBe` False
  describe "nix enabled in config file" $
    around_ (withStackDotYaml sampleConfigNixEnabled) $ do
      it "sees that the nix shell is enabled" $ do
        lc <- loadConfig' mempty
        nixEnable (configNix $ lcConfig lc) `shouldBe` True
      describe "--no-nix given on command line" $
        it "sees that the nix shell is not enabled" $ do
          lc <- loadConfig' (parseOpts ["--no-nix"])
          nixEnable (configNix $ lcConfig lc) `shouldBe` False
      describe "--nix-pure given on command line" $
        it "sees that the nix shell is enabled" $ do
          lc <- loadConfig' (parseOpts ["--nix-pure"])
          nixEnable (configNix $ lcConfig lc) `shouldBe` True
      describe "--no-nix-pure given on command line" $
        it "sees that the nix shell is enabled" $ do
          lc <- loadConfig' (parseOpts ["--no-nix-pure"])
          nixEnable (configNix $ lcConfig lc) `shouldBe` True
      it "sees that the only package asked for is glpk and asks for the correct GHC derivation" $ do
        lc <- loadConfig' mempty
        nixPackages (configNix $ lcConfig lc) `shouldBe` ["glpk"]
        v <- parseVersion "7.10.3"
        nixCompiler (GhcVersion v) `shouldBe` "haskell.compiler.ghc7103"


text:
package com.tcheckit;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;

import com.fortutech.tcheckit.ejb.sessions.Consumer;
import com.fortutech.tcheckit.ejb.sessions.TcheckitMobileBean;
import com.tcheckit.vo.DataSession;

public class MonComptePaypalActivity extends MenuBasActivity {
	private ProgressDialog progressDialog;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_mon_compte_paypal);
		if (DataSession.getInstance().getConsumer() != null && DataSession.getInstance().getConsumer().getPaypalMail() != null) {
			((EditText) findViewById(R.id.editTextNom)).setText(DataSession.getInstance().getConsumer().getPaypalMail());
		}
		RelativeLayout myLayout = (RelativeLayout) 	findViewById(R.id.relativeLayoutMonComptePaypal);
		myLayout.requestFocus();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.mon_compte_paypal, menu);
		return true;
	}

	public void sauvegarder(View view) {
		progressDialog = ProgressDialog.show(MonComptePaypalActivity.this, "", "Loading...");
		AsyncCallWS task = new AsyncCallWS();
		task.execute();
	}
    public void retour(View view) {
    	Intent intent = new Intent(view.getContext(), ReglagesActivity.class);
		startActivity(intent);
    }
	private class AsyncCallWS extends AsyncTask<String, Void, Void> {

		private AsyncCallWS() {

		}

		@Override
		protected Void doInBackground(String... params) {

			EditText paypal = (EditText) findViewById(R.id.editTextNom);
			if (paypal != null && paypal.getText() != null && paypal.getText().toString().length() > 0) {

				Consumer cs = DataSession.getInstance().getConsumer();
				cs.setPaypalMail(paypal.getText().toString());
				TcheckitMobileBean tmb = new TcheckitMobileBean();
				try {
					cs = tmb.editConsumer(cs);
					DataSession.getInstance().setConsumer(cs);

				} catch (Exception e) {
					// TODO Auto-generated catch block
					//Log.e("ERROR", e.getMessage());
					e.printStackTrace();
				}
			}
			return null;

		}

		@Override
		protected void onPostExecute(Void result) {

			progressDialog.hide();
			Intent intent = new Intent(getApplicationContext(), ReglagesActivity.class);
			startActivity(intent);
		}

		@Override
		protected void onPreExecute() {
			// Log.i("Tcheckit", "onPreExecute");

		}

		@Override
		protected void onProgressUpdate(Void... values) {
			// Log.i("Tcheckit", "onProgressUpdate");
		}
	}
	public void goMain(View view) {
		Intent intent = new Intent(this, MainActivity.class);
		startActivity(intent);
	}
}


text:
package org.bachelor.console.stat.web;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import org.bachelor.auth.domain.StatisticController;
import org.bachelor.stat.common.MSColumnChartUtil;
import org.bachelor.stat.service.ICountMenuFunctionService;
import org.bachelor.stat.vo.CountConditionVo;
import org.bachelor.stat.vo.MSColumnVo;

@Controller
@RequestMapping("stat")
public class CountMenuFunctionController {

	@Autowired
	private ICountMenuFunctionService countMenuFunctionService = null;

	@RequestMapping("index")
	public ModelAndView countIndexPage(){

		return new ModelAndView("/stat/SystemRunEfficiency");
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("systemRun")
	@ResponseBody
	public Map<String,Object> countSystemRunEfficiency(CountConditionVo cc){

		List list = countMenuFunctionService.countSystemRunEfficiency(cc);
		MSColumnVo cv = new MSColumnVo();
		//显示标题
		if(cc!=null){
			if(cc.getStartTime()!=null && !"".equals(cc.getStartTime()) &&
					cc.getEndTime()!=null && !"".equals(cc.getEndTime())){
				cv.setCaption((cc.getStartTime())+ " 至 "+(cc.getEndTime())+" 菜单运行效率");
			}else {

				cv.setCaption("菜单运行效率");

				if(cc.getStartTime()!=null && !"".equals(cc.getStartTime())){
					cv.setCaption(cc.getStartTime()+" 菜单运行效率");
				}
				if(cc.getEndTime()!=null && !"".equals(cc.getEndTime())){
					cv.setCaption(cc.getEndTime()+" 菜单运行效率");
				}
			}
		} else {
			cv.setCaption("系统运行效率");
		}
		//数值单位
		cv.setNumbersuffix("毫秒");
		Map map = new HashMap();
		map.put("json",MSColumnChartUtil.builderJsonString(list, cv));
		return map;
	}

	@RequestMapping("systemRun1")
	@ResponseBody
	public Map<String,Object> countSystemRunEfficiency1(CountConditionVo cc){

		List list = countMenuFunctionService.countSystemRunEfficiency(cc);
		MSColumnVo cv = new MSColumnVo();
		//显示标题
		if(cc!=null){
			if(cc.getStartTime()!=null && !"".equals(cc.getStartTime()) &&
					cc.getEndTime()!=null && !"".equals(cc.getEndTime())){
				cv.setCaption((cc.getStartTime())+ " 至 "+(cc.getEndTime())+" 菜单运行效率");
			}else {

				cv.setCaption("菜单运行效率");

				if(cc.getStartTime()!=null && !"".equals(cc.getStartTime())){
					cv.setCaption(cc.getStartTime()+" 菜单运行效率");
				}
				if(cc.getEndTime()!=null && !"".equals(cc.getEndTime())){
					cv.setCaption(cc.getEndTime()+" 菜单运行效率");
				}
			}
		} else {
			cv.setCaption("菜单运行效率");
		}
		//数值单位
		cv.setNumbersuffix("毫秒");
		return MSColumnChartUtil.builderChartInfo(list, cv);
	}

	@RequestMapping("test")
	@ResponseBody
	public Map<String,Object> testSave() throws Exception{
		String path[] = {"/datum/index.htm",
				"/system/addCSPage.htm",
				"/ex/addEMPage.htm",
				"/ex/index.htm",
				"/ex/addEMPage.htm"};
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		for(int len=10;len<17;len++){
			Date date = sdf.parse("2013-06-"+len+" 12:23:11");
			for(String tempPath:path){
				System.out.println(tempPath);
				for(int i=0;i<8000;i++){
					Random and = new Random();
					double db = (and.nextDouble()*1500);
					double db1 = (double)Math.rint(db);
					StatisticController sc = new StatisticController();
					sc.setCostTime(db1);
					sc.setRequestPath(tempPath);
					sc.setType("1");
					sc.setAccessDate(date);
					sc.setId(UUID.randomUUID().toString());
					countMenuFunctionService.save(sc);
				}
			}
		}
		return new HashMap();
	}
}


text:
module Fog
  module Compute
    class Cloudstack

      class Real
        # Deletes a network offering.
        #
        # {CloudStack API Reference}[http://cloudstack.apache.org/docs/api/apidocs-4.4/root_admin/deleteNetworkOffering.html]
        def delete_network_offering(*args)
          options = {}
          if args[0].is_a? Hash
            options = args[0]
            options.merge!('command' => 'deleteNetworkOffering')
          else
            options.merge!('command' => 'deleteNetworkOffering',
            'id' => args[0])
          end
          request(options)
        end
      end

    end
  end
end


text:
/*
 This is the header file for code which implements the Secure
 Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
 April 17, 1995.

 Many of the variable names in this code, especially the
 single character names, were used because those were the names
 used in the publication.

 Please read the file sha1.c for more information.

 Modified 2002 by Peter Zaitsev to better follow MySQL standards
*/

enum sha_result_codes
{
  SHA_SUCCESS = 0,
  SHA_NULL,		/* Null pointer parameter */
  SHA_INPUT_TOO_LONG,	/* input data too long */
  SHA_STATE_ERROR	/* called Input after Result */
};

#define SHA1_HASH_SIZE 20 /* Hash size in bytes */

/*
  This structure will hold context information for the SHA-1
  hashing operation
*/

typedef struct SHA1_CONTEXT
{
  ulonglong  Length;		/* Message length in bits      */
  uint32 Intermediate_Hash[SHA1_HASH_SIZE/4]; /* Message Digest  */
  int Computed;			/* Is the digest computed?	   */
  int Corrupted;		/* Is the message digest corrupted? */
  int16 Message_Block_Index;	/* Index into message block array   */
  uint8 Message_Block[64];	/* 512-bit message blocks      */
} SHA1_CONTEXT;

/*
  Function Prototypes
*/

C_MODE_START

int mysql_sha1_reset(SHA1_CONTEXT*);
int mysql_sha1_input(SHA1_CONTEXT*, const uint8 *, unsigned int);
int mysql_sha1_result(SHA1_CONTEXT* , uint8 Message_Digest[SHA1_HASH_SIZE]);

C_MODE_END


text:
var fs     = require('fs'),
    needle = require('..'),
    stream = require('stream'),
    http   = require('http'),
    should = require('should'),
    sinon  = require('sinon');

var port   = 2233;

var node_major_ver = parseInt(process.version.split('.')[0].replace('v', ''));
var node_minor_ver = parseInt(process.version.split('.')[1]);

describe('request stream length', function() {

  var server, writable;

  function createServer() {
    return http.createServer(function(req, res) {

      req.on('data', function(chunk) {
        // console.log(chunk.length);
      })

      req.on('end', function() {
        res.writeHeader(200, { 'Content-Type': 'application/json'})
        res.end(JSON.stringify({ headers: req.headers }))
      })

    })
  }

  before(function(done) {
    server = createServer();
    server.listen(port, done)
  })

  beforeEach(function() {
    writable = new stream.Readable();
    writable._read = function() {
      this.push('hello world');
      this.push(null);
    }
  })

  after(function(done) {
    server.close(done)
  })

  function send_request(opts, cb) {
    needle.post('http://localhost:' + port, writable, opts, cb)
  }

  describe('no stream_length set', function() {

    it('doesnt set Content-Length header', function(done) {
      send_request({}, function(err, resp) {
        should.not.exist(resp.body.headers['content-length']);
        done()
      })
    })

    if (node_major_ver >= 10) {
      it('returns 400 if Transfer-Encoding is set to a blank string', function(done) {
        send_request({ headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
          should.not.exist(err);
          resp.statusCode.should.eql(400);
          done()
        })
      })
    } else {
      it('doesnt work if Transfer-Encoding is set to a blank string', function(done) {
        send_request({ headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
          err.code.should.eql('ECONNRESET');
          done()
        })
      })
    }

    it('works if Transfer-Encoding is not set', function(done) {
      send_request({}, function(err, resp) {
        should.not.exist(err);
        resp.statusCode.should.eql(200);
        done()
      })
    })

  })

  describe('stream_length set to invalid value', function() {

    if (node_major_ver >= 10) {

      it('returns 400 if Transfer-Encoding is set to a blank string', function(done) {
        send_request({ stream_length: 5, headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
          should.not.exist(err);
          resp.statusCode.should.eql(400);
          done()
        })
      })

      it('returns 400 if Transfer-Encoding is not set', function(done) {
        send_request({ stream_length: 5 }, function(err, resp) {
          should.not.exist(err);
          resp.statusCode.should.eql(400);
          done()
        })
      })

    } else {

      it('doesnt work if Transfer-Encoding is set to a blank string', function(done) {
        send_request({ stream_length: 5, headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
          err.code.should.eql('ECONNRESET');
          done()
        })
      })
      it('doesnt work if Transfer-Encoding is not set', function(done) {
        send_request({ stream_length: 5 }, function(err, resp) {
          err.code.should.eql('ECONNRESET');
          done()
        })
      })

    }

  })

  describe('stream_length is set to valid value', function() {

    it('sets Content-Length header to that value', function(done) {
      send_request({ stream_length: 11 }, function(err, resp) {
        resp.body.headers['content-length'].should.eql('11');
        done()
      })
    })

    it('works if Transfer-Encoding is set to a blank string', function(done) {
      send_request({ stream_length: 11, headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
        should.not.exist(err);
        var code = node_major_ver == 10 && node_minor_ver > 15 ? 400 : 200;
        resp.statusCode.should.eql(code);
        done()
      })
    })

    it('works if Transfer-Encoding is not set', function(done) {
      send_request({ stream_length: 11 }, function(err, resp) {
        should.not.exist(err);
        resp.statusCode.should.eql(200);
        done()
      })
    })

  })

  describe('stream_length set to 0', function() {

    describe('stream with path', function() {

      var stub;

      beforeEach(function() {
        writable.path = '/foo/bar';
        stub = sinon.stub(fs, 'stat').callsFake(function(path, cb) {
          cb(null, { size: 11 })
        })
      })

      afterEach(function() {
        stub.restore();
      })

      it('sets Content-Length header to streams length', function(done) {
        send_request({ stream_length: 0 }, function(err, resp) {
          resp.body.headers['content-length'].should.eql('11');
          done()
        })
      })

      it('works if Transfer-Encoding is set to a blank string', function(done) {
        send_request({ stream_length: 0, headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
          should.not.exist(err);
          var code = node_major_ver == 10 && node_minor_ver > 15 ? 400 : 200;
          resp.statusCode.should.eql(code);
          done()
        })
      })

      it('works if Transfer-Encoding is not set', function(done) {
        send_request({ stream_length: 0 }, function(err, resp) {
          should.not.exist(err);
          resp.statusCode.should.eql(200);
          done()
        })
      })

    })

    describe('stream without path', function() {

      it('does not set Content-Length header', function(done) {
        send_request({ stream_length: 0 }, function(err, resp) {
          should.not.exist(resp.body.headers['content-length']);
          done()
        })
      })

      if (node_major_ver >= 10) {
        it('returns 400 if Transfer-Encoding is set to a blank string', function(done) {
          send_request({ stream_length: 0, headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
            should.not.exist(err);
            resp.statusCode.should.eql(400);
            done()
          })
        })
      } else {
        it('throws ECONNRESET if Transfer-Encoding is set to a blank string', function(done) {
          send_request({ stream_length: 0, headers: { 'Transfer-Encoding': '' }}, function(err, resp) {
            err.code.should.eql('ECONNRESET');
            done()
          })
        })
      }

      it('works if Transfer-Encoding is not set', function(done) {
        send_request({ stream_length: 0 }, function(err, resp) {
          should.not.exist(err);
          resp.statusCode.should.eql(200);
          done()
        })
      })
    })

  })

})


text:
"""
Tests the pred_builder module.
"""
import mock
import unittest
import numpy as np
import pandas as pd
from .context import label
from .context import config
from .context import generator
from .context import util
from .context import test_utils as tu

class LabelTestCase(unittest.TestCase):
    def setUp(self):
        config_obj = tu.sample_config()
        mock_generator_obj = mock.Mock(generator.Generator)
        util_obj = util.Util()
        self.test_obj = label.Label(config_obj, mock_generator_obj, util_obj)

    def tearDown(self):
        self.test_obj = None

    def test_init(self):
        # setup
        result = self.test_obj

        # assert
        self.assertTrue(isinstance(result.config_obj, config.Config))
        self.assertTrue(isinstance(result.generator_obj, generator.Generator))

    def test_relabel(self):
        self.test_obj.config_obj.relations = [('intext', 'text', 'text_id'),
                ('invideo', 'video', 'vid_id'),
                ('posts', 'user', 'user_id'),
                ('inment', 'mention', 'ment_id')]
        all_relations = self.test_obj.config_obj.relations
        relations = [('intext', 'text', 'text_id'),
                ('posts', 'user', 'user_id')]
        self.test_obj.util_obj.start = mock.Mock()
        self.test_obj.util_obj.end = mock.Mock()
        self.test_obj.define_file_folders = mock.Mock(return_value='data/')
        self.test_obj.read_comments = mock.Mock(return_value='df2')
        self.test_obj.filter_relations = mock.Mock(return_value=relations)
        self.test_obj.generator_obj.gen_group_ids = mock.Mock(
                return_value='f_df')
        self.test_obj.relabel_relations = mock.Mock(return_value=('labels_df',
                'new_df'))
        self.test_obj.write_new_dataframe = mock.Mock()

        self.test_obj.relabel('df')

        start = [mock.call(), mock.call('generating group ids...\n')]
        end = [mock.call('\ttime: '), mock.call('total time: ')]
        self.assertTrue(self.test_obj.util_obj.start.call_args_list == start)
        self.assertTrue(self.test_obj.util_obj.end.call_args_list == end)
        self.test_obj.define_file_folders.assert_called()
        self.test_obj.read_comments.assert_called_with('df', 'data/')
        self.test_obj.filter_relations.assert_called_with(all_relations)
        self.test_obj.generator_obj.gen_group_ids.assert_called_with('df2',
                relations)
        self.test_obj.relabel_relations.assert_called_with('f_df', relations)
        self.test_obj.write_new_dataframe.assert_called_with('new_df',
                'labels_df', 'data/')

    def test_define_file_folders(self):
        result = self.test_obj.define_file_folders()

        self.assertTrue(result == 'ind/data/soundcloud/')

    def test_read_comments(self):
        df = tu.sample_df(10)
        pd.read_csv = mock.Mock(return_value=df)
        self.test_obj.config_obj.start = 2
        self.test_obj.config_obj.end = 1000
        self.test_obj.util_obj.start = mock.Mock()
        self.test_obj.util_obj.end = mock.Mock()

        result = self.test_obj.read_comments(None, 'data/')

        self.test_obj.util_obj.start.assert_called_with('reading comments...')
        pd.read_csv.assert_called_with('data/comments.csv', nrows=1000)
        self.test_obj.util_obj.end.assert_called()
        self.assertTrue(len(result) == 8)

    def test_filter_relations(self):
        relations = [('intext', 'text', 'text_id'),
                ('invideo', 'video', 'vid_id'),
                ('posts', 'user', 'user_id'),
                ('inment', 'mention', 'ment_id')]

        result = self.test_obj.filter_relations(relations)

        exp = [('posts', 'user', 'user_id')]
        self.assertTrue(len(result) == 1)
        self.assertTrue(result == exp)

    def test_convert_dtypes(self):
        df = tu.sample_df(2)
        df['label'] = [1.0, 0.0]

        result = self.test_obj.convert_dtypes(df)

        self.assertTrue(list(result.dtypes) == [int, int, int])

    def test_relabel_relations(self):
        g_df = tu.sample_group_df()
        g_df.columns = ['user_id']
        g_df['com_id'] = [0, 1, 2, 3, 4, 5, 6]
        g_df['text_id'] = [1, 1, 1, 1, 2, 2, 7]
        g_df['label'] = [0, 1, np.nan, 0, 1, np.nan, 0]
        relations = [('intext', 'text', 'text_id'),
                ('posts', 'user', 'user_id')]
        self.test_obj.util_obj.start = mock.Mock()
        self.test_obj.util_obj.end = mock.Mock()

        result = self.test_obj.relabel_relations(g_df, relations)

        exp = 'checking if any comments need relabeling...'
        self.test_obj.util_obj.start.assert_called_with(exp)
        self.test_obj.util_obj.end.assert_called()
        self.assertTrue(list(result[0]['com_id']) == [0, 3])
        self.assertTrue(list(result[1]['com_id']) == [0, 1, 3, 4, 6])

    def test_write_new_dataframe(self):
        new_df = tu.sample_df(10)
        labels_df = tu.sample_df(10)
        new_df.to_csv = mock.Mock()
        labels_df.to_csv = mock.Mock()
        self.test_obj.util_obj.start = mock.Mock()
        self.test_obj.util_obj.end = mock.Mock()

        self.test_obj.write_new_dataframe(new_df, labels_df, 'data/')

        exp = 'writing relabeled comments...'
        self.test_obj.util_obj.start.assert_called_with(exp)
        new_df.to_csv.assert_called_with('data/modified.csv',
            encoding='utf-8', line_terminator='\n', index=None)
        labels_df.to_csv.assert_called_with('data/labels.csv', index=None)
        self.test_obj.util_obj.end.assert_called()

def test_suite():
    s = unittest.TestLoader().loadTestsFromTestCase(LabelTestCase)
    return s

if __name__ == '__main__':
    unittest.main()


text:
<?php

namespace Symfony\Bridge\Twig\Node;

use Twig\Compiler;
use Twig\Node\Expression\FunctionExpression;

/**
 * Compiles a call to {@link \Symfony\Component\Form\FormRendererInterface::renderBlock()}.
 *
 * The function name is used as block name. For example, if the function name
 * is "foo", the block "foo" will be rendered.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RenderBlockNode extends FunctionExpression
{
    public function compile(Compiler $compiler)
    {
        $compiler->addDebugInfo($this);
        $arguments = iterator_to_array($this->getNode('arguments'));
        $compiler->write('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->renderBlock(');

        if (isset($arguments[0])) {
            $compiler->subcompile($arguments[0]);
            $compiler->raw(', \''.$this->getAttribute('name').'\'');

            if (isset($arguments[1])) {
                $compiler->raw(', ');
                $compiler->subcompile($arguments[1]);
            }
        }

        $compiler->raw(')');
    }
}


text:
//do calculation in here and return an collection of finaical products
const customerData = require('../customers');
const problemData = require('../problems');

///*test case
let data = {
	price: 200000,
	downPayment: 50000,
	months: 360,
	interestRate: 5 //percentage
};
//*/

// with fixed house price
function calculateMonthlyPayment(data) {
	return new Promise((resolve, reject) => {
		if (data.price == null || data.downPayment == null || data.months == null || data.interestRate == null)
			return reject("data not enough");
		if (data.price <= 0 || data.downPayment < 0 || data.months <= 0 || data.interestRate < 0)
			return reject("meaningless data");

		if (data.downPayment >= data.price)
			return resolve(0);
		if (data.interestRate === 0)
			return resolve((data.price - data.downPayment) / data.months);

		let price = data.price,
			downPayment = data.downPayment,
			months = data.months,
			interestRate = data.interestRate / 100, // due to percentage
			monthlyInterestRate = interestRate / 12; // annual to monthly

		let monthlyPayment = monthlyInterestRate * (price - downPayment)
			/ (1 - Math.pow(1 + monthlyInterestRate, -months));
		return resolve(monthlyPayment);
	})
};

/*
// with fixed monthly payment
function calculateprice(data) {
	if (data.monthlyPayment == null || data.downPayment == null || data.months == null || data.interestRate == null)
		throw "data not enough";
	if (data.monthlyPayment <= 0 || data.downPayment < 0 || data.months <= 0 || data.interestRate < 0)
		throw "meaningless data";

	let monthlyPayment = data.monthlyPayment,
		downPayment = data.downPayment,
		months = data.months,
		interestRate = data.interestRate / 100, // due to percentage
		monthlyInterestRate = interestRate / 12; // annual to monthly

	let price = monthlyPayment * (1 - Math.pow(1 + monthlyInterestRate, -months)) / monthlyInterestRate + downPayment;
	return price;
}
*/

exportedMethods = {
	calculateProblem: (id, data) => {
		let problemsArray = [];

		return customerData.getCustomerByNodeUUID(id).then((customer) => {
			return calculateMonthlyPayment(data).then((newHouseMonthlyPayment) => {
				let monthlyIncome = customer.profile.monthlyIncome;
				let newMonthlyCosts = customer.profile.monthlyCosts.total + newHouseMonthlyPayment;

				let newSavingsRateOfIncome = (monthlyIncome - newMonthlyCosts) / monthlyIncome;

				if (newSavingsRateOfIncome < 0)
					problemsArray.push(101); // Your monthly expense is too high
				else if (newSavingsRateOfIncome < customer.profile.savingsRateOfIncome)
					problemsArray.push(102); // You're not saving enough money

				let result = {
					problems: problemsArray,
					message: "Your monthly payment for new house will be " + newHouseMonthlyPayment.toFixed(2) + "."
				};
				return result;
			});

		});
	}
}

module.exports = exportedMethods;


text:
layout: post
category: expo
title: "Breaking News"
slug: breakingnews
source: http://breakingnews.com
---

<img src="/screenshots/breakingnews.jpg">