sublime-build: Added new Benchmark build variant

This new build variant allows users to run benchmarks independently
of running their normal tests. Additional benchmark:flags can be added
to their golang.sublime-settings to further control the output or
behaviour of the benchmarks.

Fixes #13

Change-Id: I466d1d07ca6ec6c0e5d23261c13be754a6b786be
Reviewed-on: https://go-review.googlesource.com/16851
Reviewed-by: Will Bond <will@wbond.net>
Reviewed-by: Jason Buberel <jbuberel@google.com>
diff --git a/Go.sublime-build b/Go.sublime-build
index f6d23f6..9608ed4 100644
--- a/Go.sublime-build
+++ b/Go.sublime-build
@@ -12,6 +12,10 @@
             "task": "test"
         },
         {
+            "name": "Benchmark",
+            "task": "benchmark"
+        },
+        {
             "name": "Install",
             "task": "install"
         },
diff --git a/dev/go_projects/src/good/rune_len_test.go b/dev/go_projects/src/good/rune_len_test.go
index 2062458..ddefe79 100644
--- a/dev/go_projects/src/good/rune_len_test.go
+++ b/dev/go_projects/src/good/rune_len_test.go
@@ -22,3 +22,15 @@
 		}
 	}
 }
+
+func BenchmarkRuneLenResume(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		RuneLen("résumé")
+	}
+}
+
+func BenchmarkRuneLenResumeNew(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		RuneLen("résumé – new")
+	}
+}
diff --git a/dev/tests.py b/dev/tests.py
index 2316d05..89fc4f0 100644
--- a/dev/tests.py
+++ b/dev/tests.py
@@ -138,6 +138,51 @@
         self.assertEqual('success', result)
         self.assertTrue(confirm_user('Did "go test" succeed?'))
 
+    def test_benchmark(self):
+        ensure_not_ui_thread()
+
+        file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')
+
+        def _run_build(view, result_queue):
+            view.window().run_command('golang_build', {'task': 'benchmark'})
+
+        result_queue = open_file(file_path, VIEW_SETTINGS, _run_build)
+        result = wait_build(result_queue)
+        self.assertEqual('success', result)
+        self.assertTrue(confirm_user('Did "go test" succeed running all benchmarks?'))
+
+    def test_benchmark_with_bench_flag(self):
+        ensure_not_ui_thread()
+
+        file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')
+
+        def _run_build(view, result_queue):
+            view.window().run_command('golang_build', {'task': 'benchmark'})
+
+        custom_view_settings = VIEW_SETTINGS.copy()
+        custom_view_settings['benchmark:flags'] = ['-bench', 'BenchmarkRuneLenResumeNew']
+
+        result_queue = open_file(file_path, custom_view_settings, _run_build)
+        result = wait_build(result_queue)
+        self.assertEqual('success', result)
+        self.assertTrue(confirm_user('Did "go test" succeed running only BenchmarkRuneLenResumeNew?'))
+
+    def test_benchmark_with_benchmem_flag(self):
+        ensure_not_ui_thread()
+
+        file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')
+
+        def _run_build(view, result_queue):
+            view.window().run_command('golang_build', {'task': 'benchmark'})
+
+        custom_view_settings = VIEW_SETTINGS.copy()
+        custom_view_settings['benchmark:flags'] = ['-benchmem']
+
+        result_queue = open_file(file_path, custom_view_settings, _run_build)
+        result = wait_build(result_queue)
+        self.assertEqual('success', result)
+        self.assertTrue(confirm_user('Did "go test" succeed running benchmarks with memory allocation stats?'))
+
     def test_run(self):
         ensure_not_ui_thread()
 
diff --git a/docs/commands.md b/docs/commands.md
index 0c4c010..3de43f3 100644
--- a/docs/commands.md
+++ b/docs/commands.md
@@ -21,6 +21,7 @@
    - `"build"`: executes `go build -v`
    - `"run"`: executes `go run -v {current_filename}`
    - `"test"`: executes `go test -v`
+   - `"benchmark"`: executes `go test -v -bench=.`
    - `"install"`: executes `go install -v`
    - `"clean"`: executes `go clean -v`
    - `"cross_compile"`: executes `go build -v` with `GOOS` and `GOARCH` set
diff --git a/docs/configuration.md b/docs/configuration.md
index 61b614c..ac2b0ee 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -158,6 +158,7 @@
  - `build:flags` for "go build"
  - `run:flags` for "go run"
  - `test:flags` for "go test"
+ - `benchmark:flags` for "go test -bench=."
  - `install:flags` for "go install"
  - `clean:flags` for "go clean"
  - `cross_compile:flags` for "go build" with GOOS and GOARCH
diff --git a/docs/usage.md b/docs/usage.md
index 1d8263a..c47c9e0 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -20,6 +20,7 @@
  - **Build**, which executes `go build`
  - **Run**, which executes `go run` with the current filepath
  - **Test**, which executes `go test`
+ - **Benchmark**, which executes `go test -bench=.`
  - **Install**, which executes `go install`
  - **Cross-Compile (Interactive)**, which executes `go build` with `GOOS` and
    `GOARCH` set
@@ -33,6 +34,7 @@
  - `Build with: Go`
  - `Build with: Go - Run` (see [Cancelling a Build](#cancelling-a-build) below)
  - `Build with: Go - Test`
+ - `Build with: Go - Benchmark`
  - `Build with: Go - Install`
  - `Build with: Go - Cross-Compile (Interactive)`
  - `Build with: Go - Clean`
@@ -42,6 +44,7 @@
  - `Build: Build`
  - `Build: Run` (see [Cancelling a Build](#cancelling-a-build) below)
  - `Build: Test`
+ - `Build: Benchmark`
  - `Build: Install`
  - `Build: Cross-Compile (Interactive)`
  - `Build: Clean`
diff --git a/golang_build.py b/golang_build.py
index ecb0781..29345a8 100644
--- a/golang_build.py
+++ b/golang_build.py
@@ -66,7 +66,7 @@
         command palette or sublime.Window.run_command()
 
         :param task:
-            A unicode string of "build", "test", "install", "clean"
+            A unicode string of "build", "test", "benchmark", "install", "clean"
             or "cross_compile"
 
         :param flags:
@@ -151,6 +151,24 @@
             )
             return
 
+        if task == 'benchmark':
+            # Switch back to the real Go command-line arg
+            task = 'test'
+
+            # Allow user to set a regexp for the benchmarks to run
+            found_bench_flag = False
+
+            # Need to match '-bench=xyz', ['-bench','xyz'], ['-bench','.']
+            # Don't match '-benchmem' or '-benchtime'
+            # Remember user can't specify spaces in flags
+            for flag in flags:
+                if flag == '-bench' or flag.startswith('-bench='):
+                    found_bench_flag = True
+
+            # Otherwise default to running all benchmarks
+            if not found_bench_flag:
+                flags.append('-bench=.')
+
         args = [go_bin, task]
         if flags and isinstance(flags, list):
             args.extend(flags)
diff --git a/readme.md b/readme.md
index 3a93eca..cbdfeac 100644
--- a/readme.md
+++ b/readme.md
@@ -9,7 +9,7 @@
    - `go build`
    - `go run`
    - `go install`
-   - `go test`
+   - `go test` to run Tests or Benchmarks
    - `go clean`
    - Cross-compilation using `go build` with `GOOS` and `GOARCH`
  - Sublime Text command palette commands to: