github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/aagent/watchers/homekitwatcher/homekit_test.go (about)

     1  // Copyright (c) 2020-2022, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package homekitwatcher
     6  
     7  import (
     8  	"encoding/json"
     9  	"path/filepath"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/choria-io/go-choria/aagent/model"
    14  	"github.com/golang/mock/gomock"
    15  	. "github.com/onsi/ginkgo/v2"
    16  	. "github.com/onsi/gomega"
    17  )
    18  
    19  func Test(t *testing.T) {
    20  	RegisterFailHandler(Fail)
    21  	RunSpecs(t, "AAgent/Watchers/HomekitWatcher")
    22  }
    23  
    24  var _ = Describe("HomekitWatcher", func() {
    25  	var (
    26  		mockctl     *gomock.Controller
    27  		mockMachine *model.MockMachine
    28  		watch       *Watcher
    29  		now         time.Time
    30  	)
    31  
    32  	BeforeEach(func() {
    33  		mockctl = gomock.NewController(GinkgoT())
    34  		mockMachine = model.NewMockMachine(mockctl)
    35  
    36  		now = time.Unix(1606924953, 0)
    37  		mockMachine.EXPECT().Name().Return("homekit").AnyTimes()
    38  		mockMachine.EXPECT().Identity().Return("ginkgo").AnyTimes()
    39  		mockMachine.EXPECT().InstanceID().Return("1234567890").AnyTimes()
    40  		mockMachine.EXPECT().Version().Return("1.0.0").AnyTimes()
    41  		mockMachine.EXPECT().TimeStampSeconds().Return(now.Unix()).AnyTimes()
    42  		mockMachine.EXPECT().Directory().Return(".").AnyTimes()
    43  
    44  		wi, err := New(mockMachine, "ginkgo", []string{"always"}, "fail", "success", "2m", time.Second, map[string]any{})
    45  		Expect(err).ToNot(HaveOccurred())
    46  		watch = wi.(*Watcher)
    47  	})
    48  
    49  	AfterEach(func() {
    50  		mockctl.Finish()
    51  	})
    52  
    53  	Describe("setProperties", func() {
    54  		It("Should parse valid properties", func() {
    55  			prop := map[string]any{
    56  				"serial_number": "123456",
    57  				"model":         "Ginkgo",
    58  				"pin":           "12345678",
    59  				"setup_id":      "1234",
    60  				"on_when":       []string{"on"},
    61  				"off_when":      []string{"off"},
    62  				"disable_when":  []string{"disable"},
    63  				"initial":       "true",
    64  			}
    65  			Expect(watch.setProperties(prop)).ToNot(HaveOccurred())
    66  			Expect(watch.properties.SerialNumber).To(Equal("123456"))
    67  			Expect(watch.properties.Model).To(Equal("Ginkgo"))
    68  			Expect(watch.properties.Pin).To(Equal("12345678"))
    69  			Expect(watch.properties.SetupId).To(Equal("1234"))
    70  			Expect(watch.properties.ShouldOn).To(Equal([]string{"on"}))
    71  			Expect(watch.properties.ShouldOff).To(Equal([]string{"off"}))
    72  			Expect(watch.properties.ShouldDisable).To(Equal([]string{"disable"}))
    73  			Expect(watch.properties.InitialState).To(Equal(On))
    74  		})
    75  
    76  		It("Should handle initial correctly", func() {
    77  			watch.properties = &properties{Path: "/bin/sh"}
    78  			Expect(watch.setProperties(map[string]any{})).ToNot(HaveOccurred())
    79  			Expect(watch.properties.InitialState).To(Equal(Unknown))
    80  
    81  			watch.properties = &properties{Path: "/bin/sh"}
    82  			Expect(watch.setProperties(map[string]any{"initial": "true"})).ToNot(HaveOccurred())
    83  			Expect(watch.properties.InitialState).To(Equal(On))
    84  
    85  			watch.properties = &properties{Path: "/bin/sh"}
    86  			Expect(watch.setProperties(map[string]any{"initial": "false"})).ToNot(HaveOccurred())
    87  			Expect(watch.properties.InitialState).To(Equal(Off))
    88  		})
    89  
    90  		It("Should handle errors", func() {
    91  			watch.properties = &properties{Path: "/bin/sh"}
    92  			err := watch.setProperties(map[string]any{
    93  				"pin": "1",
    94  			})
    95  			Expect(err).To(MatchError("pin should be 8 characters long"))
    96  
    97  			watch.properties = &properties{Path: "/bin/sh"}
    98  			err = watch.setProperties(map[string]any{
    99  				"pin":      "12345678",
   100  				"setup_id": 1,
   101  			})
   102  			Expect(err).To(MatchError("setup_id should be 4 characters long"))
   103  
   104  			watch.properties = &properties{Path: "/bin/sh"}
   105  			err = watch.setProperties(map[string]any{
   106  				"pin":      "12345678",
   107  				"setup_id": 1234,
   108  			})
   109  			Expect(err).ToNot(HaveOccurred())
   110  		})
   111  	})
   112  
   113  	Describe("CurrentState", func() {
   114  		It("Should be a valid state", func() {
   115  			watch.previous = Off
   116  			cs := watch.CurrentState()
   117  			csj, err := cs.(*StateNotification).JSON()
   118  			Expect(err).ToNot(HaveOccurred())
   119  
   120  			event := map[string]any{}
   121  			err = json.Unmarshal(csj, &event)
   122  			Expect(err).ToNot(HaveOccurred())
   123  			delete(event, "id")
   124  
   125  			Expect(event).To(Equal(map[string]any{
   126  				"time":            "2020-12-02T16:02:33Z",
   127  				"type":            "io.choria.machine.watcher.homekit.v1.state",
   128  				"subject":         "ginkgo",
   129  				"specversion":     "1.0",
   130  				"source":          "io.choria.machine",
   131  				"datacontenttype": "application/json",
   132  				"data": map[string]any{
   133  					"id":               "1234567890",
   134  					"identity":         "ginkgo",
   135  					"machine":          "homekit",
   136  					"name":             "ginkgo",
   137  					"protocol":         "io.choria.machine.watcher.homekit.v1.state",
   138  					"type":             "homekit",
   139  					"version":          "1.0.0",
   140  					"timestamp":        float64(now.Unix()),
   141  					"previous_outcome": "off",
   142  					"path":             filepath.Join("homekit", "4bb6777bb903cae3166e826932f7fe94"),
   143  				},
   144  			}))
   145  		})
   146  	})
   147  })