Skip to content

Commit

Permalink
acceptance test for service broker
Browse files Browse the repository at this point in the history
[#139440941]
  • Loading branch information
boyang9527 committed Feb 9, 2017
1 parent 3b43097 commit 2152b03
Show file tree
Hide file tree
Showing 20 changed files with 763 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
[submodule "src/app-autoscaler"]
path = src/app-autoscaler
url = https://github.com/cloudfoundry-incubator/app-autoscaler.git
[submodule "src/github.com/cloudfoundry-incubator/cf-test-helpers"]
path = src/github.com/cloudfoundry-incubator/cf-test-helpers
url = https://github.com/cloudfoundry-incubator/cf-test-helpers.git
[submodule "src/github.com/onsi/ginkgo"]
path = src/github.com/onsi/ginkgo
url = https://github.com/onsi/ginkgo
[submodule "src/github.com/onsi/gomega"]
path = src/github.com/onsi/gomega
url = https://github.com/onsi/gomega
[submodule "src/github.com/nu7hatch/gouuid"]
path = src/github.com/nu7hatch/gouuid
url = https://github.com/nu7hatch/gouuid
[submodule "src/gopkg.in/yaml.v2"]
path = src/gopkg.in/yaml.v2
url = https://gopkg.in/yaml.v2
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ cd app-autoscaler-release


> ** cf-release deployment manifest should be cf-release/bosh-lite/deployments/cf.yml
## Acceptance test

Refer to [AutoScaler UAT guide](src/acceptance/README.md) to run acceptance test.
3 changes: 3 additions & 0 deletions src/acceptance/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/results
*config.json
*.test
129 changes: 129 additions & 0 deletions src/acceptance/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# AutoScaler UAT Guide

Tests that will NOT be introduced here are ones which could be tested at the component level.

NOTE: Because we want to parallelize execution, tests should be written in such a way as to be runnable individually. This means that tests should not depend on state in other tests,
and should not modify the CF state in such a way as to impact other tests.

1. [Test Setup](#test-setup)
1. [Install Required Dependencies](#install-required-dependencies)
1. [Test Configuration](#test-configuration)
1. [Test Execution](#test-execution)

## Test Setup

### Install Required Dependencies

Set up your golang development environment, per [golang.org](http://golang.org/doc/install).

See [cf CLI](https://github.com/cloudfoundry/cli) for instructions on installing the go version of `cf`. The latest CF CLI version are recommended.

Make sure that the go version of `cf` is accessible in your `$PATH`.

You will also need a running Cloud Foundry deployment with the AutoScaler installed to run these acceptance tests against.

### Test Configuration

You must set an environment variable `$CONFIG` which points to a JSON file that contains several pieces of data that will be used to configure the acceptance tests, e.g. telling the tests how to target your running Cloud Foundry deployment.

The following can be pasted into a terminal and will set up a sufficient `$CONFIG` to run the core test suites against a [BOSH-Lite](https://github.com/cloudfoundry/bosh-lite) deployment of CF.

```bash
cat > integration_config.json <<EOF
{
"api": "api.bosh-lite.com",
"admin_user": "admin",
"admin_password": "admin",
"apps_domain": "bosh-lite.com",
"skip_ssl_validation": true,
"use_http": true,
"service_name": "CF-AutoScaler",
"service_plan": "autoscaler-free-plan",
"api_url": "https://autoscalingapi.bosh-lite.com",
"report_interval": 120
}
EOF
export CONFIG=$PWD/integration_config.json
```

The full set of config parameters is explained below:

* `service_name` (required): The name of the registered auto-scaler service, use `cf marketplace` to determine the name.
* `api_url` (required): The url of the API service of the auto-scaler
* `report_interval` (required): How frequently metrics are collected. This value must match the value configured in your deployment.

* `api` (required): Cloud Controller API endpoint.
* `admin_user` (required): Name of a user in your CF instance with admin credentials. This admin user must have the `doppler.firehose` scope if running the `logging` firehose tests.
* `admin_password` (required): Password of the admin user above.
* `apps_domain` (required): A shared domain that tests can use to create subdomains that will route to applications also craeted in the tests.
* `skip_ssl_validation`: Set to true if using an invalid (e.g. self-signed) cert for traffic routed to your CF instance; this is generally always true for BOSH-Lite deployments of CF.
* `use_existing_user` (optional): The admin user configured above will normally be used to create a temporary user (with lesser permissions) to perform actions (such as push applications) during tests, and then delete said user after the tests have run; set this to `true` if you want to use an existing user, configured via the following properties.
* `keep_user_at_suite_end` (optional): If using an existing user (see above), set this to `true` unless you are okay having your existing user being deleted at the end. You can also set this to `true` when not using an existing user if you want to leave the temporary user around for debugging purposes after the test teardown.
* `existing_user` (optional): Name of the existing user to use.
* `existing_user_password` (optional): Password for the existing user to use.
* `backend` (optional): Set to 'diego' or 'dea' to determine the backend used. If unspecified the default backend will be used.
* `artifacts_directory` (optional): If set, `cf` CLI trace output from test runs will be captured in files and placed in this directory. [See below](#capturing-test-output) for more.
* `default_timeout` (optional): Default time (in seconds) to wait for polling assertions that wait for asynchronous results.
* `cf_push_timeout` (optional): Default time (in seconds) to wait for `cf push` commands to succeed.
* `long_curl_timeout` (optional): Default time (in seconds) to wait for assertions that `curl` slow endpoints of test applications.
* `test_password` (optional): Used to set the password for the test user. This may be needed if your CF installation has password policies.
* `timeout_scale` (optional): Used primarily to scale default timeouts for test setup and teardown actions (e.g. creating an org) as opposed to main test actions (e.g. pushing an app).
* `use_http` (optional): Set to true if you would like CF Acceptance Tests to use HTTP when making api and application requests. (default is HTTPS)

* `java_buildpack_name` (optional) [See below](#buildpack-names).
* `nodejs_buildpack_name` (optional) [See below](#buildpack-names).

#### Buildpack Names
Many tests specify a buildpack when pushing an app, so that on diego the app staging process completes in less time. The default names for the buildpacks are as follows; if you have buildpacks with different names, you can override them by setting different names:

* `java_buildpack_name: java_buildpack`
* `nodejs_buildpack_name: nodejs_buildpack`

#### Capturing Test Output
If you set a value for `artifacts_directory` in your `$CONFIG` file, then you will be able to capture `cf` trace output from failed test runs. When a test fails, look for the node id and suite name ("*Applications*" and "*2*" in the example below) in the test output:

```bash
=== RUN TestLifecycle

Running Suite: Applications
====================================
Random Seed: 1389376383
Parallel test node 2/10. Assigned 14 of 137 specs.
```

The `cf` trace output for the tests in these specs will be found in `CF-TRACE-Applications-2.txt` in the `artifacts_directory`.

### Test Execution

There are several different test suites, and you may not wish to run all the tests in all contexts, and sometimes you may want to focus individual test suites to pinpoint a failure. The default set of tests can be run via:

```bash
./bin/test_default
```

For more flexibility you can run `./bin/test` and specify many more options, e.g. which suites to run, which suites to exclude (e.g. if you want to run all but one suite), whether or not to run the tests in parallel, the number of parallel nodes to use, etc. Refer to [ginkgo documentation](http://onsi.github.io/ginkgo/) for full details.

For example, to execute all test suites, and have tests run in parallel across four processes one would run:

```bash
./bin/test -r -nodes=4
```

Be careful with this number, as it's effectively "how many apps to push at once", as nearly every example pushes an app.

To execute the acceptance tests for a specific suite, e.g. `broker`, run the following:

```bash
bin/test broker
```

The suite names correspond to directory names.

To see verbose output from `ginkgo`, use the `-v` flag.

```bash
./bin/test broker -v
```

Most of these flags and options can also be passed to the `bin/test_default` scripts as well.
Binary file added src/acceptance/assets/app/HelloWorldJavaWeb.war
Binary file not shown.
14 changes: 14 additions & 0 deletions src/acceptance/assets/app/nodeApp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "helloAutoScaler",
"version": "0.0.1",
"description": "A sample nodejs app for AutoScaler",
"scripts": {
"start": "node --max-old-space-size=600 test.js"
},
"dependencies": {
},
"repository": {},
"engines": {
"node": "0.12.x"
}
}
103 changes: 103 additions & 0 deletions src/acceptance/assets/app/nodeApp/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
var url = require('url');
var http = require('http');
//var appmetrics = require('appmetrics');
//var monitor = appmetrics.monitor();
var arr1 = [];
var arr2 = [];
var arr3 = [];
var arr4 = [];
var arr5 = [];
var arr6 = [];
var arr7 = [];
var arr8 = [];
var arr9 = [];
var arr0 = [];
var flag = 1;
var maxMem = 500; // mb
/*monitor.on('gc', function (gc) {
var processMem = process.memoryUsage();
console.log('--->[' + new Date(gc.time) + '] GC: heap: type' + gc.type +', heapSize:'+(gc.size/(1024*1024)).toFixed(2)+'m, usedHeap:'+(gc.used/(1024*1024)).toFixed(2)+'m, duration:'+gc.duration/(1000));
console.log('---->HEAP2] total: ' + (processMem.heapTotal/(1024*1024)).toFixed(2) + ' used:' + (processMem.heapUsed/(1024*1024)).toFixed(2));
});*/
setInterval(function(){
var mem1 = process.memoryUsage();
console.log('---mem used:' + (mem1.rss/(1024*1024)).toFixed(2) + 'm');
console.log('---heap total:' + (mem1.heapTotal/(1024*1024)).toFixed(2) + 'm');
console.log('---heap used:' + (mem1.heapUsed/(1024*1024)).toFixed(2) + 'm');
},5000);
var server = http.createServer(function handler(req, res) {
var params = url.parse(req.url, true).query;
var cmd = params.cmd;
var cmdType= params.mode;
if('add' == cmd){
var mem = process.memoryUsage();
if(mem.rss/(1024*1024) > maxMem ){
}
else{
//console.log('mem < 500m-------------------');
var num = params.num;
for(var i = 0; i < num; i++){
arr0.push(Math.random());
arr1.push(Math.random());
arr2.push(Math.random());
arr3.push(Math.random());
arr4.push(Math.random());
arr5.push(Math.random());
arr6.push(Math.random());
arr7.push(Math.random());
arr8.push(Math.random());
arr9.push(Math.random());
}
}

res.end('the length of array is ' + arr0.length );


}
else if('remove' == cmd){
var num = params.num;
//console.log('remove request, it will remove ' + num + 'elements from the array');
if(num > arr0.length){
num = arr0.length;
}
arr0.length = arr0.length - num;
arr1.length = arr1.length - num;
arr2.length = arr2.length - num;
arr3.length = arr3.length - num;
arr4.length = arr4.length - num;
arr5.length = arr5.length - num;
arr6.length = arr6.length - num;
arr7.length = arr7.length - num;
arr8.length = arr8.length - num;
arr9.length = arr9.length - num;
//console.log('remove request, after removing the size of array is ' + arr.length);
res.end('the length of array is ' + arr0.length );
}
else if('destroy' == cmd){
arr0.length = 0;
arr1.length = 0;
arr2.length = 0;
arr3.length = 0;
arr4.length = 0;
arr5.length = 0;
arr6.length = 0;
arr7.length = 0;
arr8.length = 0;
arr9.length = 0;
console.log('destroy request, the array size is now 0');
res.end('the length of array is ' + arr0.length );
}
else if('print' == cmd){
console.log('--------------------------->>>>>>>>>>>>>>>');
var mem = process.memoryUsage();
console.log('mem used:' + (mem.rss/(1024*1024)).toFixed(2) + 'm');
console.log('heap total:' + (mem.heapTotal/(1024*1024)).toFixed(2) + 'm');
console.log('heap used:' + (mem.heapUsed/(1024*1024)).toFixed(2) + 'm');
console.log('arr size is ' + arr0.length);
res.end('the length of array is ' + arr0.length);

}
}).listen(process.env.PORT || 3000);

console.log('App listening on port 3000');
82 changes: 82 additions & 0 deletions src/acceptance/assets/file/policy/all.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"instance_min_count": 1,
"instance_max_count": 4,
"scaling_rules": [{
"metric_type": "MemoryUsage",
"stat_window_secs": 300,
"breach_duration_secs": 600,
"threshold": 30,
"operator": "<",
"cool_down_secs": 300,
"adjustment": "-1"
}, {
"metric_type": "MemoryUsage",
"stat_window_secs": 300,
"breach_duration_secs": 600,
"threshold": 90,
"operator": ">=",
"cool_down_secs": 300,
"adjustment": "+1"
}],
"schedules": {
"timezone": "Asia/Shanghai",
"recurring_schedule": [{
"start_time": "10:00",
"end_time": "18:00",
"days_of_week": [
1,
2,
3
],
"instance_min_count": 1,
"instance_max_count": 10,
"initial_min_instance_count": 5
}, {
"start_date": "2099-06-27",
"end_date": "2099-07-23",
"start_time": "11:00",
"end_time": "19:30",
"days_of_month": [
5,
15,
25
],
"instance_min_count": 3,
"instance_max_count": 10,
"initial_min_instance_count": 5
}, {
"start_time": "10:00",
"end_time": "18:00",
"days_of_week": [
4,
5,
6
],
"instance_min_count": 1,
"instance_max_count": 10
}, {
"start_time": "11:00",
"end_time": "19:30",
"days_of_month": [
10,
20,
30
],
"instance_min_count": 1,
"instance_max_count": 10
}],
"specific_date": [{
"start_date_time": "2099-06-02T10:00",
"end_date_time": "2099-06-15T13:59",
"instance_min_count": 1,
"instance_max_count": 4,
"initial_min_instance_count": 2
}, {
"start_date_time": "2099-01-04T20:00",
"end_date_time": "2099-02-19T23:15",
"instance_min_count": 2,
"instance_max_count": 5,
"initial_min_instance_count": 3
}]
}
}
20 changes: 20 additions & 0 deletions src/acceptance/bin/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

set -e -x

export PATH="$GOPATH/bin":$PATH
go install -v github.com/onsi/ginkgo/ginkgo

bin_dir=$(dirname "${BASH_SOURCE[0]}")
pushd "${bin_dir}/.."
go list acceptance/... \
| grep -v acceptance/assets \
| xargs -I {} go test -c {}


# List of suites is passed in as a single string, so we need to re-split the argument
# The only alternative would be to split the string and then re-build the args for ginkgo
# Instead, we'll simply not add quotes around $@
# shellcheck disable=SC2068
ginkgo $@
popd
7 changes: 7 additions & 0 deletions src/acceptance/bin/test_default
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

$(dirname $0)/test \
-slowSpecThreshold=120 \
-randomizeAllSpecs \
$@ \
. broker
Loading

0 comments on commit 2152b03

Please sign in to comment.