github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/fs/bwtimetable_test.go (about)

     1  package fs
     2  
     3  import (
     4  	"encoding/json"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  // Check it satisfies the interfaces
    13  var (
    14  	_ flagger   = (*BwTimetable)(nil)
    15  	_ flaggerNP = BwTimetable{}
    16  )
    17  
    18  func TestBwTimetableSet(t *testing.T) {
    19  	for _, test := range []struct {
    20  		in   string
    21  		want BwTimetable
    22  		err  bool
    23  		out  string
    24  	}{
    25  		{"", BwTimetable{}, true, ""},
    26  		{"bad,bad", BwTimetable{}, true, ""},
    27  		{"bad bad", BwTimetable{}, true, ""},
    28  		{"bad", BwTimetable{}, true, ""},
    29  		{"1000X", BwTimetable{}, true, ""},
    30  		{"2401,666", BwTimetable{}, true, ""},
    31  		{"1061,666", BwTimetable{}, true, ""},
    32  		{"bad-10:20,666", BwTimetable{}, true, ""},
    33  		{"Mon-bad,666", BwTimetable{}, true, ""},
    34  		{"Mon-10:20,bad", BwTimetable{}, true, ""},
    35  		{
    36  			"0",
    37  			BwTimetable{
    38  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 0, Rx: 0}},
    39  			},
    40  			false,
    41  			"0",
    42  		},
    43  		{
    44  			"666",
    45  			BwTimetable{
    46  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    47  			},
    48  			false,
    49  			"666Ki",
    50  		},
    51  		{
    52  			"666:333",
    53  			BwTimetable{
    54  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    55  			},
    56  			false,
    57  			"666Ki:333Ki",
    58  		},
    59  		{
    60  			"10:20,666",
    61  			BwTimetable{
    62  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    63  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    64  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    65  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    66  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    67  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    68  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    69  			},
    70  			false,
    71  			"Sun-10:20,666Ki Mon-10:20,666Ki Tue-10:20,666Ki Wed-10:20,666Ki Thu-10:20,666Ki Fri-10:20,666Ki Sat-10:20,666Ki",
    72  		},
    73  		{
    74  			"10:20,666:333",
    75  			BwTimetable{
    76  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    77  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    78  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    79  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    80  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    81  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    82  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
    83  			},
    84  			false,
    85  			"Sun-10:20,666Ki:333Ki Mon-10:20,666Ki:333Ki Tue-10:20,666Ki:333Ki Wed-10:20,666Ki:333Ki Thu-10:20,666Ki:333Ki Fri-10:20,666Ki:333Ki Sat-10:20,666Ki:333Ki",
    86  		},
    87  		{
    88  			"11:00,333 13:40,666 23:50,10M 23:59,off",
    89  			BwTimetable{
    90  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
    91  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
    92  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
    93  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
    94  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
    95  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
    96  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
    97  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    98  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
    99  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   100  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   101  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   102  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   103  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   104  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   105  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   106  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   107  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   108  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   109  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   110  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   111  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   112  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   113  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   114  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   115  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   116  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   117  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   118  			},
   119  			false,
   120  			"Sun-11:00,333Ki Mon-11:00,333Ki Tue-11:00,333Ki Wed-11:00,333Ki Thu-11:00,333Ki Fri-11:00,333Ki Sat-11:00,333Ki Sun-13:40,666Ki Mon-13:40,666Ki Tue-13:40,666Ki Wed-13:40,666Ki Thu-13:40,666Ki Fri-13:40,666Ki Sat-13:40,666Ki Sun-23:50,10Mi Mon-23:50,10Mi Tue-23:50,10Mi Wed-23:50,10Mi Thu-23:50,10Mi Fri-23:50,10Mi Sat-23:50,10Mi Sun-23:59,off Mon-23:59,off Tue-23:59,off Wed-23:59,off Thu-23:59,off Fri-23:59,off Sat-23:59,off",
   121  		},
   122  		{
   123  			"11:00,333:666 13:40,666:off 23:50,10M:1M 23:59,off:10M",
   124  			BwTimetable{
   125  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   126  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   127  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   128  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   129  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   130  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   131  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   132  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   133  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   134  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   135  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   136  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   137  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   138  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   139  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   140  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   141  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   142  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   143  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   144  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   145  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2350, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   146  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: 10 * 1024 * 1024}},
   147  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: 10 * 1024 * 1024}},
   148  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: 10 * 1024 * 1024}},
   149  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: 10 * 1024 * 1024}},
   150  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: 10 * 1024 * 1024}},
   151  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: 10 * 1024 * 1024}},
   152  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2359, Bandwidth: BwPair{Tx: -1, Rx: 10 * 1024 * 1024}},
   153  			},
   154  			false,
   155  			"Sun-11:00,333Ki:666Ki Mon-11:00,333Ki:666Ki Tue-11:00,333Ki:666Ki Wed-11:00,333Ki:666Ki Thu-11:00,333Ki:666Ki Fri-11:00,333Ki:666Ki Sat-11:00,333Ki:666Ki Sun-13:40,666Ki:off Mon-13:40,666Ki:off Tue-13:40,666Ki:off Wed-13:40,666Ki:off Thu-13:40,666Ki:off Fri-13:40,666Ki:off Sat-13:40,666Ki:off Sun-23:50,10Mi:1Mi Mon-23:50,10Mi:1Mi Tue-23:50,10Mi:1Mi Wed-23:50,10Mi:1Mi Thu-23:50,10Mi:1Mi Fri-23:50,10Mi:1Mi Sat-23:50,10Mi:1Mi Sun-23:59,off:10Mi Mon-23:59,off:10Mi Tue-23:59,off:10Mi Wed-23:59,off:10Mi Thu-23:59,off:10Mi Fri-23:59,off:10Mi Sat-23:59,off:10Mi",
   156  		},
   157  		{
   158  			"Mon-11:00,333 Tue-13:40,666:333 Fri-00:00,10M Sat-10:00,off Sun-23:00,666",
   159  			BwTimetable{
   160  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   161  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
   162  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 0000, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   163  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1000, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   164  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   165  			},
   166  			false,
   167  			"Mon-11:00,333Ki Tue-13:40,666Ki:333Ki Fri-00:00,10Mi Sat-10:00,off Sun-23:00,666Ki",
   168  		},
   169  		{
   170  			"Mon-11:00,333 Tue-13:40,666 Fri-00:00,10M 00:01,off Sun-23:00,666:off",
   171  			BwTimetable{
   172  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   173  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   174  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 0000, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   175  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   176  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   177  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   178  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   179  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   180  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   181  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   182  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: -1}},
   183  			},
   184  			false,
   185  			"Mon-11:00,333Ki Tue-13:40,666Ki Fri-00:00,10Mi Sun-00:01,off Mon-00:01,off Tue-00:01,off Wed-00:01,off Thu-00:01,off Fri-00:01,off Sat-00:01,off Sun-23:00,666Ki:off",
   186  		},
   187  		{
   188  			// from the docs
   189  			"08:00,512 12:00,10M 13:00,512 18:00,30M 23:00,off",
   190  			BwTimetable{
   191  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 800, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   192  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 800, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   193  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 800, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   194  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 800, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   195  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 800, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   196  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 800, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   197  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 800, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   198  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1200, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   199  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1200, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   200  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1200, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   201  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1200, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   202  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1200, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   203  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1200, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   204  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1200, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   205  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1300, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   206  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1300, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   207  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1300, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   208  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1300, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   209  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1300, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   210  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1300, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   211  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1300, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   212  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1800, Bandwidth: BwPair{Tx: 30 * 1024 * 1024, Rx: 30 * 1024 * 1024}},
   213  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1800, Bandwidth: BwPair{Tx: 30 * 1024 * 1024, Rx: 30 * 1024 * 1024}},
   214  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1800, Bandwidth: BwPair{Tx: 30 * 1024 * 1024, Rx: 30 * 1024 * 1024}},
   215  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1800, Bandwidth: BwPair{Tx: 30 * 1024 * 1024, Rx: 30 * 1024 * 1024}},
   216  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1800, Bandwidth: BwPair{Tx: 30 * 1024 * 1024, Rx: 30 * 1024 * 1024}},
   217  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1800, Bandwidth: BwPair{Tx: 30 * 1024 * 1024, Rx: 30 * 1024 * 1024}},
   218  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1800, Bandwidth: BwPair{Tx: 30 * 1024 * 1024, Rx: 30 * 1024 * 1024}},
   219  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2300, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   220  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2300, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   221  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2300, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   222  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2300, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   223  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2300, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   224  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2300, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   225  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2300, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   226  			},
   227  			false,
   228  			"Sun-08:00,512Ki Mon-08:00,512Ki Tue-08:00,512Ki Wed-08:00,512Ki Thu-08:00,512Ki Fri-08:00,512Ki Sat-08:00,512Ki Sun-12:00,10Mi Mon-12:00,10Mi Tue-12:00,10Mi Wed-12:00,10Mi Thu-12:00,10Mi Fri-12:00,10Mi Sat-12:00,10Mi Sun-13:00,512Ki Mon-13:00,512Ki Tue-13:00,512Ki Wed-13:00,512Ki Thu-13:00,512Ki Fri-13:00,512Ki Sat-13:00,512Ki Sun-18:00,30Mi Mon-18:00,30Mi Tue-18:00,30Mi Wed-18:00,30Mi Thu-18:00,30Mi Fri-18:00,30Mi Sat-18:00,30Mi Sun-23:00,off Mon-23:00,off Tue-23:00,off Wed-23:00,off Thu-23:00,off Fri-23:00,off Sat-23:00,off",
   229  		},
   230  		{
   231  			// from the docs
   232  			"Mon-00:00,512 Fri-23:59,10M Sat-10:00,1M Sun-20:00,off",
   233  			BwTimetable{
   234  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 0, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   235  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2359, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 10 * 1024 * 1024}},
   236  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1000, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   237  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2000, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   238  			},
   239  			false,
   240  			"Mon-00:00,512Ki Fri-23:59,10Mi Sat-10:00,1Mi Sun-20:00,off",
   241  		},
   242  		{
   243  			// from the docs
   244  			"Mon-00:00,512 12:00,1M Sun-20:00,off",
   245  			BwTimetable{
   246  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 0, Bandwidth: BwPair{Tx: 512 * 1024, Rx: 512 * 1024}},
   247  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1200, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   248  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1200, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   249  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1200, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   250  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1200, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   251  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1200, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   252  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1200, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   253  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1200, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 1024 * 1024}},
   254  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2000, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   255  			},
   256  			false,
   257  			"Mon-00:00,512Ki Sun-12:00,1Mi Mon-12:00,1Mi Tue-12:00,1Mi Wed-12:00,1Mi Thu-12:00,1Mi Fri-12:00,1Mi Sat-12:00,1Mi Sun-20:00,off",
   258  		},
   259  	} {
   260  		tt := BwTimetable{}
   261  		err := tt.Set(test.in)
   262  		if test.err {
   263  			require.Error(t, err)
   264  		} else {
   265  			require.NoError(t, err)
   266  		}
   267  		assert.Equal(t, test.want, tt)
   268  		assert.Equal(t, test.out, tt.String())
   269  	}
   270  }
   271  
   272  func TestBwTimetableLimitAt(t *testing.T) {
   273  	for _, test := range []struct {
   274  		tt   BwTimetable
   275  		now  time.Time
   276  		want BwTimeSlot
   277  	}{
   278  		{
   279  			BwTimetable{},
   280  			time.Date(2017, time.April, 20, 15, 0, 0, 0, time.UTC),
   281  			BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: -1, Rx: -1}},
   282  		},
   283  		{
   284  			BwTimetable{
   285  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   286  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   287  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   288  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   289  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   290  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   291  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 333 * 1024}},
   292  			},
   293  			time.Date(2017, time.April, 20, 15, 0, 0, 0, time.UTC),
   294  			BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 666 * 1024}},
   295  		},
   296  		{
   297  			BwTimetable{
   298  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   299  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   300  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   301  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   302  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   303  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   304  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   305  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   306  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   307  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   308  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   309  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   310  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   311  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   312  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   313  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   314  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   315  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   316  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   317  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   318  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   319  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   320  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   321  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   322  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   323  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   324  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   325  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   326  			},
   327  			time.Date(2017, time.April, 20, 10, 15, 0, 0, time.UTC),
   328  			BwTimeSlot{DayOfTheWeek: 3, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   329  		},
   330  		{
   331  			BwTimetable{
   332  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   333  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   334  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   335  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   336  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   337  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   338  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   339  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   340  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   341  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   342  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   343  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   344  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   345  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   346  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   347  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   348  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   349  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   350  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   351  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   352  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   353  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   354  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   355  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   356  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   357  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   358  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   359  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   360  			},
   361  			time.Date(2017, time.April, 20, 11, 0, 0, 0, time.UTC),
   362  			BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   363  		},
   364  		{
   365  			BwTimetable{
   366  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   367  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   368  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   369  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   370  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   371  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   372  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   373  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   374  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   375  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   376  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   377  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   378  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   379  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   380  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   381  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   382  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   383  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   384  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   385  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   386  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   387  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   388  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   389  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   390  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   391  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   392  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   393  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   394  			},
   395  			time.Date(2017, time.April, 20, 13, 1, 0, 0, time.UTC),
   396  			BwTimeSlot{DayOfTheWeek: 4, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   397  		},
   398  		{
   399  			BwTimetable{
   400  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   401  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   402  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   403  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   404  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   405  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   406  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   407  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   408  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   409  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   410  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   411  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   412  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   413  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   414  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   415  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   416  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   417  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   418  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   419  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   420  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2301, Bandwidth: BwPair{Tx: 1024 * 1024, Rx: 102 * 1024}},
   421  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   422  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   423  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   424  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   425  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   426  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   427  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   428  			},
   429  			time.Date(2017, time.April, 20, 23, 59, 0, 0, time.UTC),
   430  			BwTimeSlot{DayOfTheWeek: 4, HHMM: 2350, Bandwidth: BwPair{Tx: -1, Rx: 1024 * 1024}},
   431  		},
   432  		{
   433  			BwTimetable{
   434  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   435  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   436  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 0000, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   437  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1000, Bandwidth: BwPair{Tx: -1, Rx: 100 * 1024}},
   438  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   439  			},
   440  			time.Date(2017, time.April, 20, 23, 59, 0, 0, time.UTC),
   441  			BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   442  		},
   443  		{
   444  			BwTimetable{
   445  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   446  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   447  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 0000, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   448  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1000, Bandwidth: BwPair{Tx: -1, Rx: 100 * 1024}},
   449  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   450  			},
   451  			time.Date(2017, time.April, 21, 23, 59, 0, 0, time.UTC),
   452  			BwTimeSlot{DayOfTheWeek: 5, HHMM: 0000, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   453  		},
   454  		{
   455  			BwTimetable{
   456  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1100, Bandwidth: BwPair{Tx: 333 * 1024, Rx: 33 * 1024}},
   457  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1340, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   458  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 0000, Bandwidth: BwPair{Tx: 10 * 1024 * 1024, Rx: 1 * 1024 * 1024}},
   459  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1000, Bandwidth: BwPair{Tx: -1, Rx: 100 * 1024}},
   460  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 2300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   461  			},
   462  			time.Date(2017, time.April, 17, 10, 59, 0, 0, time.UTC),
   463  			BwTimeSlot{DayOfTheWeek: 0, HHMM: 2300, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 66 * 1024}},
   464  		},
   465  	} {
   466  		slot := test.tt.LimitAt(test.now)
   467  		assert.Equal(t, test.want, slot)
   468  	}
   469  }
   470  
   471  func TestBwTimetableUnmarshalJSON(t *testing.T) {
   472  	for _, test := range []struct {
   473  		in   string
   474  		want BwTimetable
   475  		err  bool
   476  	}{
   477  		{
   478  			`"Mon-10:20,bad"`,
   479  			BwTimetable(nil),
   480  			true,
   481  		},
   482  		{
   483  			`"0"`,
   484  			BwTimetable{
   485  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 0, Rx: 0}},
   486  			},
   487  			false,
   488  		},
   489  		{
   490  			`"666"`,
   491  			BwTimetable{
   492  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   493  			},
   494  			false,
   495  		},
   496  		{
   497  			`"666:333"`,
   498  			BwTimetable{
   499  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
   500  			},
   501  			false,
   502  		},
   503  		{
   504  			`"10:20,666"`,
   505  			BwTimetable{
   506  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   507  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   508  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   509  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   510  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   511  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   512  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   513  			},
   514  			false,
   515  		},
   516  	} {
   517  		var bwt BwTimetable
   518  		err := json.Unmarshal([]byte(test.in), &bwt)
   519  		if test.err {
   520  			require.Error(t, err, test.in)
   521  		} else {
   522  			require.NoError(t, err, test.in)
   523  		}
   524  		assert.Equal(t, test.want, bwt)
   525  	}
   526  }
   527  
   528  func TestBwTimetableMarshalJSON(t *testing.T) {
   529  	for _, test := range []struct {
   530  		in   BwTimetable
   531  		want string
   532  	}{
   533  		{
   534  			BwTimetable{
   535  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 0, Rx: 0}},
   536  			},
   537  			`"0"`,
   538  		},
   539  		{
   540  			BwTimetable{
   541  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   542  			},
   543  			`"666Ki"`,
   544  		},
   545  		{
   546  			BwTimetable{
   547  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 0, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 333 * 1024}},
   548  			},
   549  			`"666Ki:333Ki"`,
   550  		},
   551  		{
   552  			BwTimetable{
   553  				BwTimeSlot{DayOfTheWeek: 0, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   554  				BwTimeSlot{DayOfTheWeek: 1, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   555  				BwTimeSlot{DayOfTheWeek: 2, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   556  				BwTimeSlot{DayOfTheWeek: 3, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   557  				BwTimeSlot{DayOfTheWeek: 4, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   558  				BwTimeSlot{DayOfTheWeek: 5, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   559  				BwTimeSlot{DayOfTheWeek: 6, HHMM: 1020, Bandwidth: BwPair{Tx: 666 * 1024, Rx: 666 * 1024}},
   560  			},
   561  			`"Sun-10:20,666Ki Mon-10:20,666Ki Tue-10:20,666Ki Wed-10:20,666Ki Thu-10:20,666Ki Fri-10:20,666Ki Sat-10:20,666Ki"`,
   562  		},
   563  	} {
   564  		got, err := json.Marshal(test.in)
   565  		require.NoError(t, err, test.want)
   566  		assert.Equal(t, test.want, string(got))
   567  	}
   568  }