gitee.com/mysnapcore/mysnapd@v0.1.0/timeutil/synchronized_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2021 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 timeutil_test 21 22 import ( 23 "errors" 24 "fmt" 25 26 "github.com/godbus/dbus" 27 . "gopkg.in/check.v1" 28 29 "gitee.com/mysnapcore/mysnapd/dbusutil" 30 "gitee.com/mysnapcore/mysnapd/testutil" 31 "gitee.com/mysnapcore/mysnapd/timeutil" 32 ) 33 34 const ( 35 timedate1BusName = "org.freedesktop.timedate1" 36 timedate1ObjectPath = "/org/freedesktop/timedate1" 37 ) 38 39 type mockTimedate1 struct { 40 conn *dbus.Conn 41 42 NTPSynchronized bool 43 44 getPropertyCalled []string 45 } 46 47 func newMockTimedate1() (*mockTimedate1, error) { 48 conn, err := dbusutil.SessionBusPrivate() 49 if err != nil { 50 return nil, err 51 } 52 53 server := &mockTimedate1{ 54 conn: conn, 55 } 56 57 reply, err := conn.RequestName(timedate1BusName, dbus.NameFlagDoNotQueue) 58 if err != nil { 59 conn.Close() 60 return nil, err 61 } 62 63 if reply != dbus.RequestNameReplyPrimaryOwner { 64 conn.Close() 65 return nil, fmt.Errorf("cannot obtain bus name %q", timedate1BusName) 66 } 67 68 return server, nil 69 } 70 71 func (server *mockTimedate1) Export() { 72 server.conn.Export(timedate1Api{server}, timedate1ObjectPath, "org.freedesktop.DBus.Properties") 73 } 74 75 func (server *mockTimedate1) Stop() error { 76 if _, err := server.conn.ReleaseName(timedate1BusName); err != nil { 77 return err 78 } 79 return server.conn.Close() 80 } 81 82 type timedate1Api struct { 83 server *mockTimedate1 84 } 85 86 func (a timedate1Api) Get(iff, prop string) (dbus.Variant, *dbus.Error) { 87 a.server.getPropertyCalled = append(a.server.getPropertyCalled, fmt.Sprintf("if=%s;prop=%s", iff, prop)) 88 return dbus.MakeVariant(a.server.NTPSynchronized), nil 89 } 90 91 type syncedSuite struct { 92 testutil.BaseTest 93 testutil.DBusTest 94 } 95 96 var _ = Suite(&syncedSuite{}) 97 98 func (s *syncedSuite) SetUpTest(c *C) { 99 s.BaseTest.SetUpTest(c) 100 s.DBusTest.SetUpTest(c) 101 102 restore := dbusutil.MockOnlySystemBusAvailable(s.SessionBus) 103 s.AddCleanup(restore) 104 } 105 106 func (s *syncedSuite) TearDownTest(c *C) { 107 s.DBusTest.TearDownTest(c) 108 s.BaseTest.TearDownTest(c) 109 } 110 111 func (s *syncedSuite) TestIsNTPSynchronized(c *C) { 112 backend, err := newMockTimedate1() 113 c.Assert(err, IsNil) 114 defer backend.Stop() 115 backend.Export() 116 117 for _, v := range []bool{true, false} { 118 backend.getPropertyCalled = nil 119 backend.NTPSynchronized = v 120 121 synced, err := timeutil.IsNTPSynchronized() 122 c.Assert(err, IsNil) 123 c.Check(synced, Equals, v) 124 125 c.Check(backend.getPropertyCalled, DeepEquals, []string{ 126 "if=org.freedesktop.timedate1;prop=NTPSynchronized", 127 }) 128 } 129 } 130 131 func (s *syncedSuite) TestIsNTPSynchronizedStrangeEr(c *C) { 132 backend, err := newMockTimedate1() 133 c.Assert(err, IsNil) 134 defer backend.Stop() 135 // Note that we did not export anything here - this error is a bit 136 // artificial 137 138 _, err = timeutil.IsNTPSynchronized() 139 c.Check(err, ErrorMatches, `cannot check for ntp sync: Object does not implement the interface`) 140 } 141 142 func (s *syncedSuite) TestIsNTPSynchronizedNoTimedatectlNoErr(c *C) { 143 // note that there is no mock timedate1 created so we are on an empty bus 144 synced, err := timeutil.IsNTPSynchronized() 145 c.Check(err, ErrorMatches, `cannot find org.freedesktop.timedate1 dbus service: .*`) 146 c.Check(errors.As(err, &timeutil.NoTimedate1Error{}), Equals, true) 147 c.Check(synced, Equals, false) 148 }