github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/snap/cmd_wait_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2018 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package main_test
    21  
    22  import (
    23  	"encoding/json"
    24  	"fmt"
    25  	"net/http"
    26  	"time"
    27  
    28  	. "gopkg.in/check.v1"
    29  
    30  	snap "github.com/snapcore/snapd/cmd/snap"
    31  )
    32  
    33  func (s *SnapSuite) TestCmdWaitHappy(c *C) {
    34  	restore := snap.MockWaitConfTimeout(10 * time.Millisecond)
    35  	defer restore()
    36  
    37  	n := 0
    38  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
    39  		c.Check(r.Method, Equals, "GET")
    40  		c.Check(r.URL.Path, Equals, "/v2/snaps/system/conf")
    41  
    42  		fmt.Fprintln(w, fmt.Sprintf(`{"type":"sync", "status-code": 200, "result": {"seed.loaded":%v}}`, n > 1))
    43  		n++
    44  	})
    45  
    46  	_, err := snap.Parser(snap.Client()).ParseArgs([]string{"wait", "system", "seed.loaded"})
    47  	c.Assert(err, IsNil)
    48  
    49  	// ensure we retried a bit but make the check not overly precise
    50  	// because this will run in super busy build hosts that where a
    51  	// 10 millisecond sleep actually takes much longer until the kernel
    52  	// hands control back to the process
    53  	c.Check(n > 2, Equals, true)
    54  }
    55  
    56  func (s *SnapSuite) TestCmdWaitMissingConfKey(c *C) {
    57  	n := 0
    58  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
    59  		n++
    60  	})
    61  
    62  	_, err := snap.Parser(snap.Client()).ParseArgs([]string{"wait", "snapName"})
    63  	c.Assert(err, ErrorMatches, "the required argument `<key>` was not provided")
    64  
    65  	c.Check(n, Equals, 0)
    66  }
    67  
    68  func (s *SnapSuite) TestTrueishJSON(c *C) {
    69  	tests := []struct {
    70  		v      interface{}
    71  		b      bool
    72  		errStr string
    73  	}{
    74  		// nil
    75  		{nil, false, ""},
    76  		// bool
    77  		{true, true, ""},
    78  		{false, false, ""},
    79  		// string
    80  		{"a", true, ""},
    81  		{"", false, ""},
    82  		// json.Number
    83  		{json.Number("1"), true, ""},
    84  		{json.Number("-1"), true, ""},
    85  		{json.Number("0"), false, ""},
    86  		{json.Number("1.0"), true, ""},
    87  		{json.Number("-1.0"), true, ""},
    88  		{json.Number("0.0"), false, ""},
    89  		// slices
    90  		{[]interface{}{"a"}, true, ""},
    91  		{[]interface{}{}, false, ""},
    92  		{[]string{"a"}, true, ""},
    93  		{[]string{}, false, ""},
    94  		// arrays
    95  		{[2]interface{}{"a", "b"}, true, ""},
    96  		{[0]interface{}{}, false, ""},
    97  		{[2]string{"a", "b"}, true, ""},
    98  		{[0]string{}, false, ""},
    99  		// maps
   100  		{map[string]interface{}{"a": "a"}, true, ""},
   101  		{map[string]interface{}{}, false, ""},
   102  		{map[interface{}]interface{}{"a": "a"}, true, ""},
   103  		{map[interface{}]interface{}{}, false, ""},
   104  		// invalid
   105  		{int(1), false, "cannot test type int for truth"},
   106  	}
   107  	for _, t := range tests {
   108  		res, err := snap.TrueishJSON(t.v)
   109  		if t.errStr == "" {
   110  			c.Check(err, IsNil)
   111  		} else {
   112  			c.Check(err, ErrorMatches, t.errStr)
   113  		}
   114  		c.Check(res, Equals, t.b, Commentf("unexpected result for %v (%T), did not get expected %v", t.v, t.v, t.b))
   115  	}
   116  }
   117  
   118  func (s *SnapSuite) TestCmdWaitIntegration(c *C) {
   119  	restore := snap.MockWaitConfTimeout(2 * time.Millisecond)
   120  	defer restore()
   121  
   122  	var tests = []struct {
   123  		v        string
   124  		willWait bool
   125  	}{
   126  		// not-waiting
   127  		{"1.0", false},
   128  		{"-1.0", false},
   129  		{"0.1", false},
   130  		{"-0.1", false},
   131  		{"1", false},
   132  		{"-1", false},
   133  		{`"a"`, false},
   134  		{`["a"]`, false},
   135  		{`{"a":"b"}`, false},
   136  		// waiting
   137  		{"0", true},
   138  		{"0.0", true},
   139  		{"{}", true},
   140  		{"[]", true},
   141  		{`""`, true},
   142  		{"null", true},
   143  	}
   144  
   145  	testValueCh := make(chan string, 2)
   146  	n := 0
   147  	s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) {
   148  		testValue := <-testValueCh
   149  		c.Check(r.Method, Equals, "GET")
   150  		c.Check(r.URL.Path, Equals, "/v2/snaps/system/conf")
   151  
   152  		fmt.Fprintln(w, fmt.Sprintf(`{"type":"sync", "status-code": 200, "result": {"test.value":%v}}`, testValue))
   153  		n++
   154  	})
   155  
   156  	for _, t := range tests {
   157  		n = 0
   158  		testValueCh <- t.v
   159  		if t.willWait {
   160  			// a "trueish" value to ensure wait does not wait forever
   161  			testValueCh <- "42"
   162  		}
   163  
   164  		_, err := snap.Parser(snap.Client()).ParseArgs([]string{"wait", "system", "test.value"})
   165  		c.Assert(err, IsNil)
   166  		if t.willWait {
   167  			// we waited once, then got a non-wait value
   168  			c.Check(n, Equals, 2)
   169  		} else {
   170  			// no waiting happened
   171  			c.Check(n, Equals, 1)
   172  		}
   173  	}
   174  }