From 276f8cccf644faddf5cf5b8b25ce64e9e63e1c9f Mon Sep 17 00:00:00 2001
From: Nick Craig-Wood <nick@craig-wood.com>
Date: Mon, 24 Jun 2019 13:18:52 +0100
Subject: [PATCH] rc: return current settings if core/bwlimit called without
 parameters

---
 fs/accounting/token_bucket.go      | 60 +++++++++++++++++++++---------
 fs/accounting/token_bucket_test.go | 59 +++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+), 17 deletions(-)
 create mode 100644 fs/accounting/token_bucket_test.go

diff --git a/fs/accounting/token_bucket.go b/fs/accounting/token_bucket.go
index a59268a31..bb017a25f 100644
--- a/fs/accounting/token_bucket.go
+++ b/fs/accounting/token_bucket.go
@@ -133,25 +133,31 @@ func init() {
 	rc.Add(rc.Call{
 		Path: "core/bwlimit",
 		Fn: func(ctx context.Context, in rc.Params) (out rc.Params, err error) {
-			ibwlimit, ok := in["rate"]
-			if !ok {
-				return out, errors.Errorf("parameter rate not found")
+			if in["rate"] != nil {
+				bwlimit, err := in.GetString("rate")
+				if err != nil {
+					return out, err
+				}
+				var bws fs.BwTimetable
+				err = bws.Set(bwlimit)
+				if err != nil {
+					return out, errors.Wrap(err, "bad bwlimit")
+				}
+				if len(bws) != 1 {
+					return out, errors.New("need exactly 1 bandwidth setting")
+				}
+				bw := bws[0]
+				SetBwLimit(bw.Bandwidth)
 			}
-			bwlimit, ok := ibwlimit.(string)
-			if !ok {
-				return out, errors.Errorf("value must be string rate=%v", ibwlimit)
+			bytesPerSecond := int64(-1)
+			if tokenBucket != nil {
+				bytesPerSecond = int64(tokenBucket.Limit())
 			}
-			var bws fs.BwTimetable
-			err = bws.Set(bwlimit)
-			if err != nil {
-				return out, errors.Wrap(err, "bad bwlimit")
+			out = rc.Params{
+				"rate":           fs.SizeSuffix(bytesPerSecond).String(),
+				"bytesPerSecond": bytesPerSecond,
 			}
-			if len(bws) != 1 {
-				return out, errors.New("need exactly 1 bandwidth setting")
-			}
-			bw := bws[0]
-			SetBwLimit(bw.Bandwidth)
-			return rc.Params{"rate": bw.Bandwidth.String()}, nil
+			return out, nil
 		},
 		Title: "Set the bandwidth limit.",
 		Help: `
@@ -159,11 +165,31 @@ This sets the bandwidth limit to that passed in.
 
 Eg
 
-    rclone rc core/bwlimit rate=1M
     rclone rc core/bwlimit rate=off
+    {
+        "bytesPerSecond": -1,
+        "rate": "off"
+    }
+    rclone rc core/bwlimit rate=1M
+    {
+        "bytesPerSecond": 1048576,
+        "rate": "1M"
+    }
+
+
+If the rate parameter is not suppied then the bandwidth is queried
+
+    rclone rc core/bwlimit
+    {
+        "bytesPerSecond": 1048576,
+        "rate": "1M"
+    }
 
 The format of the parameter is exactly the same as passed to --bwlimit
 except only one bandwidth may be specified.
+
+In either case "rate" is returned as a human readable string, and
+"bytesPerSecond" is returned as a number.
 `,
 	})
 }
diff --git a/fs/accounting/token_bucket_test.go b/fs/accounting/token_bucket_test.go
new file mode 100644
index 000000000..d9980fdde
--- /dev/null
+++ b/fs/accounting/token_bucket_test.go
@@ -0,0 +1,59 @@
+package accounting
+
+import (
+	"context"
+	"testing"
+
+	"github.com/ncw/rclone/fs/rc"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	"golang.org/x/time/rate"
+)
+
+func TestRcBwLimit(t *testing.T) {
+	call := rc.Calls.Get("core/bwlimit")
+	assert.NotNil(t, call)
+
+	// Set
+	in := rc.Params{
+		"rate": "1M",
+	}
+	out, err := call.Fn(context.Background(), in)
+	require.NoError(t, err)
+	assert.Equal(t, rc.Params{
+		"bytesPerSecond": int64(1048576),
+		"rate":           "1M",
+	}, out)
+	assert.Equal(t, rate.Limit(1048576), tokenBucket.Limit())
+
+	// Query
+	in = rc.Params{}
+	out, err = call.Fn(context.Background(), in)
+	require.NoError(t, err)
+	assert.Equal(t, rc.Params{
+		"bytesPerSecond": int64(1048576),
+		"rate":           "1M",
+	}, out)
+
+	// Reset
+	in = rc.Params{
+		"rate": "off",
+	}
+	out, err = call.Fn(context.Background(), in)
+	require.NoError(t, err)
+	assert.Equal(t, rc.Params{
+		"bytesPerSecond": int64(-1),
+		"rate":           "off",
+	}, out)
+	assert.Nil(t, tokenBucket)
+
+	// Query
+	in = rc.Params{}
+	out, err = call.Fn(context.Background(), in)
+	require.NoError(t, err)
+	assert.Equal(t, rc.Params{
+		"bytesPerSecond": int64(-1),
+		"rate":           "off",
+	}, out)
+
+}