diff -Nru fuji-0.3.0/app.go fuji-1.0.2/app.go --- fuji-0.3.0/app.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/app.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,16 +18,16 @@ log "github.com/Sirupsen/logrus" "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/device" "github.com/shiguredo/fuji/gateway" - "github.com/shiguredo/fuji/inidef" ) // Start make command channel and start gateway. func Start(configPath string) { - conf, err := inidef.LoadConfig(configPath) + conf, err := config.LoadConfig(configPath) if err != nil { - log.Fatalf("loading ini file faild, %v", err) + log.Fatalf("loading config file faild, %v", err) } commandChannel := make(chan string) @@ -39,7 +39,7 @@ } // StartByFileWithChannel starts Gateway with command Channel -func StartByFileWithChannel(conf inidef.Config, commandChannel chan string) error { +func StartByFileWithChannel(conf config.Config, commandChannel chan string) error { gw, err := gateway.NewGateway(conf) if err != nil { log.Fatalf("gateway create error, %v", err) diff -Nru fuji-0.3.0/AUTHORS fuji-1.0.2/AUTHORS --- fuji-0.3.0/AUTHORS 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/AUTHORS 2016-03-23 04:35:15.000000000 +0000 @@ -1,3 +1,4 @@ Kazutaka Ogaki Shirou WAKAYAMA Nakai Ryosuke +Tatsuhiko Kubo diff -Nru fuji-0.3.0/broker/broker.go fuji-1.0.2/broker/broker.go --- fuji-0.3.0/broker/broker.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/broker/broker.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,15 +24,19 @@ "strconv" "strings" - MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" log "github.com/Sirupsen/logrus" + MQTT "github.com/eclipse/paho.mqtt.golang" validator "gopkg.in/validator.v2" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/message" "github.com/shiguredo/fuji/utils" ) +const ( + defaultWillTopic = "will" +) + type Broker struct { GatewayName string Name string `validate:"max=256,regexp=[^/]+,validtopic"` @@ -43,9 +47,13 @@ Password string `validate:"max=256"` RetryInterval int `validate:"min=0"` TopicPrefix string `validate:"max=256"` + IsWill bool WillMessage []byte `validate:"max=256"` + WillTopic string `validate:"max=256,validtopic"` Tls bool CaCert string `validate:"max=256"` + ClientCert string `validate:"max=256"` + ClientKey string `validate:"max=256"` TLSConfig *tls.Config Subscribed Subscribed // list of subscribed topics @@ -75,35 +83,47 @@ // init is automatically invoked at initial time. func init() { - validator.SetValidationFunc("validtopic", inidef.ValidMqttPublishTopic) + validator.SetValidationFunc("validtopic", config.ValidMqttPublishTopic) } // NewTLSConfig returns TLS config from CA Cert file path. -func NewTLSConfig(caCertFilePath string) (*tls.Config, error) { +func NewTLSConfig(b *Broker) (*tls.Config, error) { certPool := x509.NewCertPool() - pemCerts, err := ioutil.ReadFile(caCertFilePath) + pemCerts, err := ioutil.ReadFile(b.CaCert) if err != nil { - return nil, inidef.Error("Cert File could not be read.") + return nil, config.Error(fmt.Sprintf("Cert File: %s could not be read.", b.CaCert)) } appendCertOk := certPool.AppendCertsFromPEM(pemCerts) if appendCertOk != true { - return nil, inidef.Error("Server Certificate parse failed") + return nil, config.Error("Server Certificate parse failed") } - - // only server certificate checked - return &tls.Config{ + ret := &tls.Config{ RootCAs: certPool, ClientAuth: tls.NoClientCert, ClientCAs: nil, // InsecureSkipVerify = verify that cert contents // match server. IP matches what is in cert etc. InsecureSkipVerify: true, - }, nil + } + if b.ClientCert != "" { + if b.ClientKey == "" { + return nil, config.Error("Client certificate requires private key") + } + // client certificate also checked + cert, err := tls.LoadX509KeyPair(b.ClientCert, b.ClientKey) + if err != nil { + return nil, err + } + ret.ClientAuth = tls.RequireAndVerifyClientCert + ret.Certificates = []tls.Certificate{cert} + ret.ClientCAs = certPool + } + return ret, nil } -// NewBrokers returns []*Broker from inidef.Config. +// NewBrokers returns []*Broker from config.Config. // If validation failes, retrun error. -func NewBrokers(conf inidef.Config, gwChan chan message.Message) (Brokers, error) { +func NewBrokers(conf config.Config, gwChan chan message.Message) (Brokers, error) { var brokers Brokers for _, section := range conf.Sections { @@ -123,6 +143,7 @@ Username: values["username"], Password: values["password"], TopicPrefix: values["topic_prefix"], + IsWill: false, WillMessage: willMsg, Tls: false, CaCert: "", @@ -130,6 +151,19 @@ Subscribed: NewSubscribed(), GwChan: gwChan, } + + for k, v := range values { + if k == "will_message" { + broker.IsWill = true + w, err := utils.ParsePayload(v) + if err != nil { + log.Warnf("parse error will_message, %v", err) + } + log.Debugf("will_message, %v", w) + broker.WillMessage = w + } + } + priority := 1 if section.Arg != "" { priority, err = strconv.Atoi(section.Arg) @@ -155,16 +189,33 @@ } } - if values["tls"] == "true" && values["cacert"] != "" { - // validate certificate + if values["tls"] == "true" { + if values["cacert"] == "" { + return nil, fmt.Errorf("cacert must be set") + } broker.Tls = true broker.CaCert = values["cacert"] - broker.TLSConfig, err = NewTLSConfig(broker.CaCert) + + // check client certificate + if values["client_cert"] != "" && values["client_key"] != "" { + // client certificate authentication + + broker.ClientCert = values["client_cert"] + broker.ClientKey = values["client_key"] + } + + // validate certificate + broker.TLSConfig, err = NewTLSConfig(broker) if err != nil { return nil, err } } + if values["will_topic"] != "" { + broker.WillTopic = strings.Join([]string{broker.TopicPrefix, values["will_topic"]}, "/") + } else { + broker.WillTopic = strings.Join([]string{broker.TopicPrefix, broker.GatewayName, defaultWillTopic}, "/") + } // Validation if err := validator.Validate(broker); err != nil { return brokers, err @@ -262,7 +313,7 @@ case "status": // status device topic structure is difference topicString = strings.Join([]string{b.TopicPrefix, msg.Topic}, "/") default: - topicString = strings.Join([]string{b.TopicPrefix, b.GatewayName, msg.Sender, msg.Type}, "/") + topicString = strings.Join([]string{b.TopicPrefix, b.GatewayName, msg.Sender, msg.Type, "publish"}, "/") } topic := message.TopicString{ @@ -308,8 +359,8 @@ opts.SetUsername(b.Username) opts.SetPassword(b.Password) - if !inidef.IsNil(b.WillMessage) { - willTopic := strings.Join([]string{b.TopicPrefix, gwName, "will"}, "/") + if b.IsWill { + willTopic := b.WillTopic willQoS := 0 opts.SetBinaryWill(willTopic, b.WillMessage, byte(willQoS), true) } diff -Nru fuji-0.3.0/broker/broker_test.go fuji-1.0.2/broker/broker_test.go --- fuji-0.3.0/broker/broker_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/broker/broker_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,19 +20,20 @@ "github.com/stretchr/testify/assert" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/message" ) +/* func TestNewBrokersSingle(t *testing.T) { assert := assert.New(t) - iniStr := ` -[broker "sango/2"] - host = 192.168.1.22 + configStr := ` +[[broker."sango/2"]] + host = "192.168.1.22" port = 1883 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b, err := NewBrokers(conf, make(chan message.Message)) assert.Nil(err) assert.Equal(1, len(b)) @@ -41,20 +42,20 @@ assert.Equal("", b[0].TopicPrefix) assert.Equal([]byte{}, b[0].WillMessage) } - +*/ func TestNewBrokersSettings(t *testing.T) { assert := assert.New(t) - iniStr := ` -[broker "sango/2"] - host = 192.168.1.22 - port = 1883 - username = usr - password = pass - topic_prefix = pre - will_message = will + configStr := ` +[[broker."sango/2"]] + host = "192.168.1.22" + port = 1883 + username = "usr" + password = "pass" + topic_prefix = "pre" + will_message = "will" ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b, err := NewBrokers(conf, make(chan message.Message)) assert.Nil(err) assert.Equal(1, len(b)) @@ -67,15 +68,15 @@ func TestNewBrokersMulti(t *testing.T) { assert := assert.New(t) - iniStr := ` -[broker "sango/1"] - host = 192.168.1.22 + configStr := ` +[[broker."sango/1"]] + host = "192.168.1.22" port = 1883 -[broker "sango/2"] - host = 192.168.1.22 +[[broker."sango/2"]] + host = "192.168.1.22" port = 1883 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b, err := NewBrokers(conf, make(chan message.Message)) assert.Nil(err) assert.Equal(2, len(b)) @@ -88,45 +89,45 @@ assert := assert.New(t) // invalid host, too long - iniStr := ` -[broker "sango/2"] - host = 192.168.1.22aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + configStr := ` +[[broker."sango/2"]] + host = "192.168.1.22aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" port = 1883 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewBrokers(conf, make(chan message.Message)) assert.NotNil(err) } func TestBrokerValidationPort(t *testing.T) { assert := assert.New(t) - iniStr := ` -[broker "sango/2"] - host = 192.168.1.22 + configStr := ` +[[broker."sango/2"]] + host = "192.168.1.22" port = 65536 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewBrokers(conf, make(chan message.Message)) assert.NotNil(err) } func TestBrokerValidationPriority(t *testing.T) { assert := assert.New(t) - iniStr := ` - [broker "sango/10"] - host = 192.168.1.22 + configStr := ` + [[broker."sango/10"]] + host = "192.168.1.22" port = 1883 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewBrokers(conf, make(chan message.Message)) assert.NotNil(err) - iniStr = ` - [broker "sango/0"] - host = 192.168.1.22 + configStr = ` + [[broker."sango/0"]] + host = "192.168.1.22" port = 1883 ` - conf, err = inidef.LoadConfigByte([]byte(iniStr)) + conf, err = config.LoadConfigByte([]byte(configStr)) _, err = NewBrokers(conf, make(chan message.Message)) assert.NotNil(err) @@ -134,44 +135,73 @@ func TestBrokerValidationWill(t *testing.T) { assert := assert.New(t) - iniStr := ` - [broker "sango/1"] - host = 192.168.1.22 + configStr := ` + [[broker."sango/1"]] + host = "192.168.1.22" port = 1883 - will_message = will + will_message = "will" ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b, err := NewBrokers(conf, make(chan message.Message)) assert.Nil(err) assert.Equal(1, len(b)) assert.Equal([]byte("will"), b[0].WillMessage) - iniStr = ` - [broker "sango/1"] - host = 192.168.1.22 + configStr = ` + [[broker."sango/1"]] + host = "192.168.1.22" port = 1883 - will_message = \x01\x0f + will_message = "\\x01\\x0f" ` - conf, err = inidef.LoadConfigByte([]byte(iniStr)) + conf, err = config.LoadConfigByte([]byte(configStr)) b, err = NewBrokers(conf, make(chan message.Message)) assert.Nil(err) assert.Equal(1, len(b)) assert.Equal([]byte{1, 15}, b[0].WillMessage) // either will message has invalid binary, not error, just warn - iniStr = ` - [broker "sango/1"] - host = 192.168.1.22 + configStr = ` + [[broker."sango/1"]] + host = "192.168.1.22" port = 1883 - will_message = \x01\x0fffff + will_message = "\\x01\\x0fffff" ` - conf, err = inidef.LoadConfigByte([]byte(iniStr)) + conf, err = config.LoadConfigByte([]byte(configStr)) b, err = NewBrokers(conf, make(chan message.Message)) assert.Nil(err) assert.Equal(1, len(b)) assert.Equal([]byte{1, 15}, b[0].WillMessage) } +func TestBrokerValidationTls(t *testing.T) { + assert := assert.New(t) + + // check broker validation + configStr := ` + [[broker."sango/1"]] + host = "localhost" + port = 8883 + tls = true + cacert = "../tests/mosquitto/ca.pem" +` + conf, err := config.LoadConfigByte([]byte(configStr)) + b, err := NewBrokers(conf, make(chan message.Message)) + assert.Nil(err) + assert.Equal(1, len(b)) + + // check broker validation fail if cacert is missing + configStr = ` + [[broker."sango/1"]] + host = "localhost" + port = 8883 + tls = true +` + conf, err = config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + b, err = NewBrokers(conf, make(chan message.Message)) + assert.NotNil(err) +} + func TestGenerateTopic(t *testing.T) { assert := assert.New(t) b := &Broker{ @@ -186,14 +216,14 @@ } t1, err := b.GenerateTopic(msg1) assert.Nil(err) - assert.Equal("prefix/gw/s/t", t1.Str) + assert.Equal("prefix/gw/s/t/publish", t1.Str) msg2 := &message.Message{ Sender: "s1", } t2, err := b.GenerateTopic(msg2) assert.Nil(err) - assert.Equal("prefix/gw/s1/", t2.Str) + assert.Equal("prefix/gw/s1//publish", t2.Str) } func TestGenerateTopicStatus(t *testing.T) { diff -Nru fuji-0.3.0/broker/subscribe.go fuji-1.0.2/broker/subscribe.go --- fuji-0.3.0/broker/subscribe.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/broker/subscribe.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ "sync" log "github.com/Sirupsen/logrus" + + "github.com/shiguredo/fuji/message" ) type Subscribed struct { @@ -64,12 +66,12 @@ delete(s.list, topic) return nil } -func (b *Broker) AddSubscribed(deviceName string, qos byte) error { - t := strings.Join([]string{b.TopicPrefix, b.GatewayName, deviceName}, "/") +func (b *Broker) AddSubscribed(deviceTopic message.TopicString, qos byte) error { + t := strings.Join([]string{b.TopicPrefix, b.GatewayName, deviceTopic.Str}, "/") log.Infof("subscribe: %#v", t) return b.Subscribed.Add(t, qos) } -func (b *Broker) DeleteSubscribed(deviceName string, qos byte) error { - t := strings.Join([]string{b.TopicPrefix, b.GatewayName, deviceName}, "/") +func (b *Broker) DeleteSubscribed(deviceTopic message.TopicString, qos byte) error { + t := strings.Join([]string{b.TopicPrefix, b.GatewayName, deviceTopic.Str}, "/") return b.Subscribed.Delete(t) } diff -Nru fuji-0.3.0/BUILD.rst fuji-1.0.2/BUILD.rst --- fuji-0.3.0/BUILD.rst 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/BUILD.rst 2016-03-23 04:35:15.000000000 +0000 @@ -2,7 +2,7 @@ 時雨堂 MQTTゲートウェイ Fuji ビルド方法 ####################################### -:バージョン: 0.2.0 +:バージョン: 1.0.2 fujiはGoプログラミング言語で記述されています。 fujiをデバッグ、拡張するためにソースコードをビルドするまでのおおよその流れは以下のようになります。 @@ -50,8 +50,8 @@ まずお使いのOSが32bit版であるか、64bit版であるかを確認します。 適応するMSIファイル(インストールパッケージ)の名前は次のようになりますので、ダウンロードページからダウンロードしてください。 -- 32bit版OS : go1.4.2.windows-386.msi -- 64bit版OS : go1.4.2.windows-amd64.msi +- 32bit版OS : go1.5.3.windows-386.msi +- 64bit版OS : go1.5.3.windows-amd64.msi ダウンロードしたファイルを開けば、インストールが開始されます。 diff -Nru fuji-0.3.0/CHANGELOG.rst fuji-1.0.2/CHANGELOG.rst --- fuji-0.3.0/CHANGELOG.rst 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/CHANGELOG.rst 2016-03-23 04:35:15.000000000 +0000 @@ -1,119 +1,126 @@ -######### -ChangeLog -######### +######## +CHANGELOG +######## +UPDATE + backword compatible change +ADD + backword compatible enhancement +CHANGE + backworkd incompatible change +FIX + bug fix -0.3.0 +1.0.2 ===== -:release: 2015-10-07 +:release: 2016-03-23 -- update godep dependency and user latest paho MQTT library -- Changed to use go 1.5 -- Customized cli.VersionPrinter +UPDATE -0.2.3 -===== +- build: switched from godep to glide. -:release: 2015-05-19 +FIX -- Fixed versioning in downloads -- Add "How To Release" to README.rst +- device: serial subscribe topic mismatch -0.2.2 +1.0.1 ===== -:release: 2015-05-19 +:release: 2016-02-29 -- Fixed consuming CPU bug in dummy device. +UPDATE +- build: Golang version 1.6 -0.2.1 +1.0.0 ===== -:release: 2015-04-29 +:release: 2016-02-15 -- Fixed ARM5 and ARM7 build settings +UPDATE -0.2.0 -===== +- build: Golang version 1.5.3 +- build: Remove gopsutil/common from Godep.json. -**Paid support and customize has been started** +ADD -:release: 2015-04-22 +- config: validate and abort in case of invalid configuration. +- status: status report on IP address. +- gateway: MQTT client authentication using clients certification. +- gateway: added test in the case of empty gateway name. +- gateway: will_topic configuration capability. +- test: TLS testcase added using mosquitto broker on docker. -- MQTT 3.1.1 -- MQTT over TLS -- Sending Device Status using `gopsutil `_ +CHANGE - - CPU and memory information - - Interval +- config: configuration syntax modified to use type string to show device type. +- config: fuji exits when there are irregular configuration formats in toml. +- config: switch configuration file format from ini to toml. +- gateway: publish/subscribe topic changed to distinguish both. -- Will Message +FIX - - ``will_message = ""`` in config. - - topic_prefix - - will message will be sent to fixed topic. ex: ``/will`` -- Retain +- test: will testcase fix. - - ``retain = true`` in config. -- Binary Message +0.3.0 +===== - - To send binary, specify like ``\\x00\\x12`` -- Work on `Armadillo-IoT `_ +:release: 2015-10-07 - - MQTT over TLS via 3G -- Work on Intel Edison -- Infinity connection retry -- Subscribe - - ``subscribe = true`` in config file. - - Subscribe fixed topic (ex: ``/``). When a message comes, write the payload to the device. -- Binary for `Armadillo-IoT `_ +UPDATE - - ARM5 -- Packaged file for Raspberry Pi Model B+ +- build: refactored Makefile +- build: change to go 1.5.1 +- build: generated control from control.in. +- build: update library dependency on paho and gopsutil. +- optimization: call regexp.MustCompile() once on start-up. +- refactored: moved inidef/porttype.go to device/porttype.go. - - Raspbian, ARM6 +ADD -- Packaged file for Intel Edison +- app: customized cli.VersionPrinter. - - Yocto Linux +FIX -- Message sending Retry +- fix DeviceChannel multiplexing - - If sending message failed, retry sometimes. -- Redundant server and switching each other - - After retry to a primary broker failed, switch to secondary broker. - - ``[device "sango/1"]`` and ``[device "sango/2"]`` -- Multiple Broker +0.2.3 +===== - - Connect to each broker independently. +:release: 2015-05-19 -- Japanese Document +UPDATE -0.1.0 -===== +- document: add "How To Release" to README.rst. -:release: 2015-02-13 +FIX -- First internal release +- build: fixed version TAG and CHANGELOG description. -- Serial port device - - Acquire real sensor data from EnOcean Device +0.2.2 +====== -- Dummy Device -- MQTT 3.1 -- MQTT Broker +:release: 2015-05-19 - - single broker only +FIX -- Topic_prefix -- dpkg install +- device: remove default clause to not consume all cpu. - - Raspbian +0.2.1 +===== -- Work on `Raspberry Pi `_ -- Package file for `Raspberry Pi` -- Japanese Document +:release: 2015-04-29 + +FIX + +- build: fixed ARM5 and ARM7 build settings. + +0.2.0 +====== + +First public release + +:release: 2015-04-22 diff -Nru fuji-0.3.0/circle.yml fuji-1.0.2/circle.yml --- fuji-0.3.0/circle.yml 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/circle.yml 2016-03-23 04:35:15.000000000 +0000 @@ -10,7 +10,7 @@ PATH: "/home/ubuntu/go/bin:${PATH}:${GOPATH}/bin" GO15VENDOREXPERIMENT: 1 GOROOT: "/home/ubuntu/go" - GOVERSION: "1.5.1" + GOVERSION: "1.6" services: - docker @@ -18,21 +18,25 @@ cache_directories: - "/home/ubuntu/go" override: + - CURRENTGOVERSION=`go version | awk '{print $3}'` - if [[ ! -e /home/ubuntu/go/bin/go ]]; then cd /home/ubuntu; curl https://storage.googleapis.com/golang/go${GOVERSION}.linux-amd64.tar.gz | tar -xz; fi + - if [[ "go${GOVERSION}" != ${CURRENTGOVERSION} ]]; then cd /home/ubuntu; rm -rf go; curl https://storage.googleapis.com/golang/go${GOVERSION}.linux-amd64.tar.gz | tar -xz; fi - rm -rf ${GOPATH}/src/${REPO_PATH} - mkdir -p ${GOPATH}/src/${ORG_PATH} - cp -r ../fuji ${GOPATH}/src/${ORG_PATH} - - go get github.com/kr/godep - - cd ${GOPATH}/src/${REPO_PATH} && godep restore + - go get github.com/Masterminds/glide + - cd ${GOPATH}/src/${REPO_PATH} && glide install test: override: - go version - go get -u github.com/mitchellh/gox - - docker run -d -p 1883:1883 shiguredo/mosquitto /usr/local/sbin/mosquitto ; sleep 20 - - godep go build: + - docker run -d -p 1883:1883 -p 8883:8883 -p 9883:9883 -p 8080:8080 -v /home/ubuntu/.go_workspace/src/github.com/shiguredo/fuji/tests/mosquitto:/mosquitto --name fuji-test-mosquitto shiguredo/mosquitto ; sleep 20 + - go build: pwd: ../.go_workspace/src/${REPO_PATH} - - godep go test -coverpkg github.com/shiguredo/fuji ./...: + - make build: + pwd: ../.go_workspace/src/${REPO_PATH} + - go test -coverpkg github.com/shiguredo/fuji $(glide novendor): pwd: ../.go_workspace/src/${REPO_PATH} post: - make arm5 arm6 arm7 linux_386 linux_amd64 raspi raspi2 armadillo edison: @@ -43,4 +47,4 @@ branch: master commands: - go get github.com/tcnksm/ghr - - ghr -u shiguredo -r fuji --replace --prerelease pre-release /home/ubuntu/.go_workspace/src/github.com/shiguredo/fuji/downloads \ No newline at end of file + - ghr -u shiguredo -r fuji --replace --prerelease pre-release /home/ubuntu/.go_workspace/src/github.com/shiguredo/fuji/downloads diff -Nru fuji-0.3.0/cmd/fuji/main.go fuji-1.0.2/cmd/fuji/main.go --- fuji-0.3.0/cmd/fuji/main.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/cmd/fuji/main.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ app.Flags = []cli.Flag{ cli.StringFlag{ Name: "conf, c", - Value: "/etc/fuji-gw/config.ini", + Value: "/etc/fuji-gw/config.toml", Usage: "config filepath", EnvVar: "FUJI_CONFIG_FILE", }, @@ -57,7 +57,7 @@ func printVersion(c *cli.Context) { fmt.Fprintf(c.App.Writer, `%v version %v Compiler: %s %s -Copyright 2015 Shiguredo Inc. +Copyright 2015-2016 Shiguredo Inc. `, c.App.Name, c.App.Version, diff -Nru fuji-0.3.0/config/load.go fuji-1.0.2/config/load.go --- fuji-0.3.0/config/load.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/config/load.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,279 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "fmt" + "github.com/BurntSushi/toml" + "io/ioutil" + "strconv" + "strings" +) + +func buildUniqueValueMap(values map[string]interface{}) map[string]string { + valueMap := make(map[string]string) + + for k, v := range values { + switch v.(type) { + case int64: + valueMap[k] = strconv.FormatInt(v.(int64), 10) + case bool: + valueMap[k] = strconv.FormatBool(v.(bool)) + default: + valueMap[k] = v.(string) + } + } + + return valueMap +} + +func buildMultipleValueMap(values []map[string]interface{}) map[string]string { + valueMap := make(map[string]string) + + for _, m := range values { + for k, v := range m { + switch v.(type) { + case int64: + valueMap[k] = strconv.FormatInt(v.(int64), 10) + case bool: + valueMap[k] = strconv.FormatBool(v.(bool)) + default: + valueMap[k] = v.(string) + } + } + } + + return valueMap +} + +func getGatewayName(gatewaySectionMap SectionMap) (string, error) { + for name, value := range gatewaySectionMap { + if name == "name" { + gatewayName := value.(string) + if gatewayName == "" { + return "", fmt.Errorf("gateway has not name") + } + return gatewayName, nil + } + } + return "", nil +} + +func addGatewaySection(configSections []ConfigSection, gatewaySectionMap SectionMap) []ConfigSection { + valueMap := make(ValueMap) + for name, value := range gatewaySectionMap { + + switch value.(type) { + case int64: + valueMap[name] = strconv.FormatInt(value.(int64), 10) + case bool: + valueMap[name] = strconv.FormatBool(value.(bool)) + default: + valueMap[name] = value.(string) + } + + } + + if len(valueMap) > 0 { + rt := ConfigSection{ + Title: "gateway", + Type: "gateway", + Values: valueMap, + } + configSections = append(configSections, rt) + } + + return configSections +} + +func addStatusSections(configSections []ConfigSection, statusSectionMap SectionMap) []ConfigSection { + valueMap := make(ValueMap) + for name, value := range statusSectionMap { + + switch value.(type) { + case int64: + valueMap[name] = strconv.FormatInt(value.(int64), 10) + case bool: + valueMap[name] = strconv.FormatBool(value.(bool)) + case []map[string]interface{}: + // do nothing + default: + valueMap[name] = value.(string) + } + + } + if len(valueMap) > 0 { + rt := ConfigSection{ + Title: "status", + Type: "status", + Values: valueMap, + } + configSections = append(configSections, rt) + } + + for name, value := range statusSectionMap { + + valueMap := make(ValueMap) + switch value.(type) { + case []map[string]interface{}: + { + m := value.([]map[string]interface{}) + for _, v := range m { + for k, vv := range v { + switch vv.(type) { + case int64: + valueMap[k] = strconv.FormatInt(vv.(int64), 10) + case bool: + valueMap[k] = strconv.FormatBool(vv.(bool)) + default: + valueMap[k] = vv.(string) + } + } + } + } + } + + if len(valueMap) > 0 { + rt := ConfigSection{ + Title: "status", + Type: "status", + Name: name, + Values: valueMap, + } + configSections = append(configSections, rt) + } + } + + return configSections +} + +func addConfigSections(configSections []ConfigSection, title string, sectionMap SectionMap) ([]ConfigSection, error) { + for name, values := range sectionMap { + t := strings.Split(name, "/") + if len(t) > 2 { + return configSections, fmt.Errorf("invalid section(slash), %v", t) + } + + var valueMap map[string]string + + switch values.(type) { + case map[string]interface{}: + if title == "broker" { + msgFmt := "invalid broker section. not [broker.\"%s\"] but [[broker.\"%s\"]]" + return configSections, fmt.Errorf(msgFmt, name, name) + } + valueMap = buildUniqueValueMap(values.(map[string]interface{})) + case []map[string]interface{}: + if title == "device" { + msgFmt := "invalid device section. not [[device.\"%s\"]] but [device.\"%s\"]" + return configSections, fmt.Errorf(msgFmt, name, name) + } + valueMap = buildMultipleValueMap(values.([]map[string]interface{})) + default: + return configSections, fmt.Errorf("valid section not found", name) + } + + if len(valueMap) == 0 { + continue + } + + rt := ConfigSection{ + Title: title, + Type: title, + Name: t[0], + Values: valueMap, + } + + if len(t) == 2 { // if args exists, store it + rt.Arg = t[1] + } + + configSections = append(configSections, rt) + } + + return configSections, nil +} + +// LoadConfig loads toml format file from confPath arg and returns []ConfigSection. +// ConfigSection has a Type, Name and arg. +// example: +// [[broker."sango"]] +// [[broker."sango/1"]] +// [[broker."sango/2"]] +// +// ret = [ +// ConfigSection{Type: "broker", Name: "sango"}, +// ConfigSection{Type: "broker", Name: "sango", Arg: "1"}, +// ConfigSection{Type: "broker", Name: "sango", Arg: "2"}, +// ] +func LoadConfig(confPath string) (Config, error) { + dat, err := ioutil.ReadFile(confPath) + if err != nil { + return Config{}, err + } + + return LoadConfigByte(dat) +} + +// LoadConfigByte returns []ConfigSection from []byte. +// This is invoked from LoadConfig. +func LoadConfigByte(conf []byte) (Config, error) { + config := Config{} + var configToml ConfigToml + + if err := toml.Unmarshal(conf, &configToml); err != nil { + return config, err + } + + var sections []ConfigSection + var bn []string + + // gateway section + gatewayName, err := getGatewayName(configToml.Gateway) + if err != nil { + return config, err + } + config.GatewayName = gatewayName + sections = addGatewaySection(sections, configToml.Gateway) + + // status section + sections = addStatusSections(sections, configToml.Status) + + // broker sections + sections, err = addConfigSections(sections, "broker", configToml.Brokers) + if err != nil { + return config, err + } + + // device sections + sections, err = addConfigSections(sections, "device", configToml.Devices) + if err != nil { + return config, err + } + + // broker names + for name, _ := range configToml.Brokers { + t := strings.Split(name, "/") + if len(t) > 2 { + continue + } + bn = append(bn, t[0]) + } + + config.Sections = sections + config.BrokerNames = bn + + return config, nil +} diff -Nru fuji-0.3.0/config/load_test.go fuji-1.0.2/config/load_test.go --- fuji-0.3.0/config/load_test.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/config/load_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,63 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDupGateway(t *testing.T) { + assert := assert.New(t) + + configStr := ` +[[gateway]] + name = "ham" + max_retry_count = 30 +` + _, err := LoadConfigByte([]byte(configStr)) + assert.NotNil(err) + +} + +func TestUniqBroker(t *testing.T) { + assert := assert.New(t) + + configStr := ` +[broker."sango/2"] + host = "192.168.1.22" + port = 1883 +` + _, err := LoadConfigByte([]byte(configStr)) + assert.NotNil(err) + +} + +func TestDupDevice(t *testing.T) { + assert := assert.New(t) + + configStr := ` +[[device."dora/dummy"]] + broker = "sango" + qos = 1 + dummy = true + interval = 10 + payload = "Hello world." +` + _, err := LoadConfigByte([]byte(configStr)) + assert.NotNil(err) + +} diff -Nru fuji-0.3.0/config/toml.go fuji-1.0.2/config/toml.go --- fuji-0.3.0/config/toml.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/config/toml.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,126 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "errors" + "reflect" + "regexp" + "unicode/utf8" +) + +var ( + ReU0 *regexp.Regexp + ReWild *regexp.Regexp +) + +type Config struct { + GatewayName string + BrokerNames []string + + Sections []ConfigSection +} + +type ValueMap map[string]string + +type ConfigSection struct { + Title string + Type string + Name string + Arg string + + Values ValueMap +} + +type ConfigToml struct { + Gateway SectionMap `toml:"gateway"` + Brokers SectionMap `toml:"broker"` + Devices SectionMap `toml:"device"` + Status SectionMap `toml:"status"` +} + +type SectionMap map[string]interface{} + +type AnyError interface{} + +type Error string + +func (e Error) Error() string { + return string(e) +} + +// NilOrString defines the value is nil or empty +type NilOrString interface{} + +// init is automatically invoked at initial time. +func init() { + ReU0 = regexp.MustCompile("\u0000") + ReWild = regexp.MustCompile("[+#]+") +} + +func IsNil(str NilOrString) bool { + if str == nil { + return true + } + return false +} +func String(str NilOrString) string { + stringValue, ok := str.(string) + if ok == false { + return ("nil") + } + return stringValue +} + +// ValidMqttPublishTopic validates the Topic is validate or not +// This is used with validator packages. +func ValidMqttPublishTopic(v interface{}, param string) error { + str := reflect.ValueOf(v) + if str.Kind() != reflect.String { + return errors.New("ValidMqttPublishTopic only validates strings") + } + if !utf8.ValidString(str.String()) { + return errors.New("not a valid UTF8 string") + } + + if ReU0.FindString(str.String()) != "" { + return errors.New("Topic SHALL NOT include \\U0000 character") + } + + if ReWild.FindString(str.String()) != "" { + return errors.New("SHALL NOT MQTT pub-topic include wildard character") + } + return nil +} + +// SearchSection finds the section matched condition args. +func SearchSection(sections *[]ConfigSection, t, arg string) *ConfigSection { + for _, section := range *sections { + if section.Type == t && section.Arg == arg { + return §ion + } + } + return nil +} + +// SearchDeviceType find the device section matched type name string +func SearchDeviceType(sections *[]ConfigSection, arg string) *ConfigSection { + for _, section := range *sections { + if section.Type == "device" && section.Values["type"] == arg { + return §ion + } + } + return nil +} diff -Nru fuji-0.3.0/config/toml_test.go fuji-1.0.2/config/toml_test.go --- fuji-0.3.0/config/toml_test.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/config/toml_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,59 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSearchBrokerSection(t *testing.T) { + assert := assert.New(t) + + conf, err := LoadConfig("../tests/testing_conf.toml") + assert.Nil(err) + + section := SearchSection(&conf.Sections, "broker", "1") + assert.NotNil(section) + + section = SearchSection(&conf.Sections, "broker", "2") + assert.NotNil(section) + + section = SearchSection(&conf.Sections, "broker", "3") + assert.Nil(section) + +} + +func TestSearchDeviceType(t *testing.T) { + assert := assert.New(t) + + conf, err := LoadConfig("../tests/testing_conf.toml") + assert.Nil(err) + + section := SearchDeviceType(&conf.Sections, "serial") + assert.NotNil(section) + assert.Equal("device", section.Type) + assert.Equal("serial", section.Values["type"]) + + section = SearchDeviceType(&conf.Sections, "dummy") + assert.NotNil(section) + assert.Equal("device", section.Type) + assert.Equal("dummy", section.Values["type"]) + + section = SearchDeviceType(&conf.Sections, "notfound") + assert.Nil(section) + +} diff -Nru fuji-0.3.0/config.ini.example fuji-1.0.2/config.ini.example --- fuji-0.3.0/config.ini.example 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/config.ini.example 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -[gateway] - - name = ham - -[broker "sango"] - - host = 192.0.2.10 - port = 1883 - - username = fuji-gw - password = 123 - - topic_prefix = fuji-gw@example.com - retry_interval = 10 - -[broker "akane"] - - host = 192.0.2.20 - port = 8883 - tls = true - cert = /path/to/cert - - username = fuji-gw - password = 456 - -[device "spam/serial"] - - broker = sango - qos = 0 - - serial = /dev/tty.ble - baud = 9600 - size = 4 - type = BLE - -[device "beacon/serial"] - - broker = sango - qos = 2 - - serial = /dev/tty.enocean - baud = 115200 - size = 8 - type = EnOcean - -[device "dora/dummy"] - - broker = akane - qos = 2 - - interval = 10 - payload = Hello world. diff -Nru fuji-0.3.0/config.toml.example fuji-1.0.2/config.toml.example --- fuji-0.3.0/config.toml.example 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/config.toml.example 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,284 @@ +## Fuji configuration examples +## version: 1.0.2 +## +## Copyright 2015-2016 Shiguredo Inc. +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. + +###################################### +## section 1. part by part description +## + +## +## 1.1 gateway +## + +## only name parameter required + +# [gateway] +# name = "spam" + +## +## 1.2 broker +## + +## no authentication, just connect and optional parameters +# + +# [[broker."sango"]] +# +# host = "192.0.2.10" +# port = 1883 +# +# topic_prefix = "sayo@example.com" +# retry_count = 7 +# retry_interval = 3 +# will_message = "hello world" + + +## password authentication +# + +# [[broker."sango"]] +# +# host = "192.0.2.10" +# port = 1883 +# +# username = "sayo" +# password = "456" + + +## TLS connection with servers CA certificate +# + +# [[broker."akane"]] +# +# host = "192.0.2.20" +# port = 8883 +# tls = true +# cacert = "/path/to/cacert" +# +# username = "sayo" +# password = "456" + + +## Client certificate authentication +# + +# [[broker."akane"]] +# +# host = "192.0.2.20" +# port = 9883 +# tls = true +# cacert = "/path/to/cacert" +# client_cert = "/path/to/client_cert" +# client_key = "/path/to/client_private_key" + +## +## 1.3 Devices (dummy/serial) +## + +# device common part : broker and QoS specification + +## 1.3.1 Dummy device : report fixed data periodically + +# # name of device +# [device."spam"] +# +# # specify broker to connect +# broker = "sango" +# +# # QoS level +# qos = 0 + +# # device type : dummy +# type = "dummy" +# interval = 30 +# payload = "Hello world." + + +## 1.3.2 Serial device : report and output data via serial port + +# # name of device +# [device."spam"] +# +# # specify broker to connect +# broker = "sango" +# +# # QoS level +# qos = 0 +# +# # device type : serial +# type = "serial" +# +# # serial port path +# serial = /dev/tty.usbserial +# +# # +# baud = 57600 + + +## +## 1.4 Status +## + +## Status common part +# + +# [status] +# +# # specify broker to connect +# broker = "sango" +# +# # QoS level +# qos = 0 +# +# # report interval in second +# interval = 10 +# + +## status type specific part +# + +## cpu : various cpu time fragments can be specified +# +# [[status."cpu"]] +# cpu_times = "user, system, idle, nice, iowait, irq, softirq, guest" + + +## memory : any of memory usage type can be specified +# +# [[status."memory"]] +# virtual_memory = "total, available, percent, used, free" + + +## ip address : interface device names can be specified. +# +# [[status."ip_address"]] +# interface = "lo0, en0" +# +# # or, 'all' is used to list up them all +# +# [[status."ip_address"]] +# interface = "all"` + +########################################### +## section 2. complete configuration samples +## +## Notice: To use following samples, please remove first comment character of each line. + +## +## 2.1 Dummy device : to publish message periodically +## +## - publish topic: /ham/spam/dummy/publish +## - published message: "Hello world." +## - publish interval: 30 seconds + +# +# [gateway] +# name = "ham" +# +# [[broker."sango"]] +# host = "127.0.0.1" +# port = 1883 +# username = "USERNAME" +# password = "PASSWORD" +# +# [device."spam"] +# broker = "sango" +# qos = 0 +# type = "dummy" +# interval = 30 +# payload = "Hello world." + + +## +## 2.2 Serial device : to publish message from serial connection +## +## serial port is /dev/tty.usbserial and serial connection bit rate is 57600bps + +# +# [gateway] +# name = "ham" +# +# [[broker."sango"]] +# host = "127.0.0.1" +# port = 1883 +# username = "USERNAME" +# password = "PASSWORD" +# +# [device."spam"] +# broker = "sango" +# qos = 0 +# type = "serial" +# +# serial = /dev/tty.usbserial +# baud = 57600 + + +## +## 2.3 Subscribe topic and output received message against serial device +## +## The publish data from the serial port with the topic of '/ham/spam/serial/publish'. +## And received message with the topic of '/ham/spam/serial/subscribe' is written to the serial port. + +# [gateway] +# name = "ham" +# +# [[broker."sango"]] +# host = "127.0.0.1" +# port = 1883 +# username = "USERNAME" +# password = "PASSWORD" +# +# [device."spam"] +# broker = "sango" +# qos = 0 +# type = "serial" +# subscribe = true +# +# serial = /dev/tty.usbserial +# baud = 57600 + + +## +## 2.4 Publish status of CPU, memory, IP address periodically +## + +# [gateway] +# name = "ham" +# +# [[broker."sango"]] +# host = "127.0.0.1" +# port = 1883 +# username = "USERNAME" +# password = "PASSWORD" +# +# [status] +# broker = "sango" +# qos = 0 +# interval = 10 +# +# [[status."cpu"]] +# cpu_times = "user, system, idle, nice, iowait, irq, softirq, guest" +# +# [[status."memory"]] +# virtual_memory = "total, available, percent, used, free" +# +# [[status."ip_address"]] +# interface = "lo0, en0" + +## Note: in case of ip_address of all interfaces are required, use "all" as below + +# [[status."ip_address"]] +# interface = "all" diff -Nru fuji-0.3.0/debian/changelog fuji-1.0.2/debian/changelog --- fuji-0.3.0/debian/changelog 2016-02-26 15:18:02.000000000 +0000 +++ fuji-1.0.2/debian/changelog 2016-07-15 04:12:18.000000000 +0000 @@ -1,3 +1,12 @@ +fuji (1.0.2-1) unstable; urgency=medium + + * New upstream released. + * Fix FTBFS in testing (undefined: cpu.CPUTimes). (Closes: #829675) + - Add debian/patches/fix_function_name. + * Update Standards-Version to 3.9.8. + + -- Nobuhiro Iwamatsu Fri, 06 May 2016 17:45:56 +0900 + fuji (0.3.0-1) unstable; urgency=low * Initial release (Closes: #815928) diff -Nru fuji-0.3.0/debian/control fuji-1.0.2/debian/control --- fuji-0.3.0/debian/control 2016-02-26 17:36:41.000000000 +0000 +++ fuji-1.0.2/debian/control 2016-06-30 09:48:11.000000000 +0000 @@ -3,18 +3,21 @@ Priority: optional Maintainer: Nobuhiro Iwamatsu Build-Depends: debhelper (>= 9), dh-systemd, - dh-golang, - golang-go, - golang-github-sirupsen-logrus-dev, - golang-github-pborman-uuid-dev, - golang-golang-x-net-dev, - golang-eclipse-paho-dev, - golang-github-shirou-gopsutil-dev, - golang-gopkg-validator.v2-dev, - golang-codegangsta-cli-dev, - golang-github-go-ini-ini-dev, - golang-github-tarm-serial-dev -Standards-Version: 3.9.7 + dh-golang, + golang-go, + golang-github-sirupsen-logrus-dev, + golang-github-pborman-uuid-dev, + golang-golang-x-net-dev, + golang-golang-x-sys-dev, + golang-eclipse-paho-dev, + golang-github-shirou-gopsutil-dev, + golang-gopkg-validator.v2-dev, + golang-codegangsta-cli-dev, + golang-github-go-ini-ini-dev, + golang-github-tarm-serial-dev, + golang-github-burntsushi-toml-dev, + golang-github-stretchr-testify-dev +Standards-Version: 3.9.8 Homepage: https://github.com/shiguredo/fuji.git Vcs-Git: git://anonscm.debian.org/collab-maint/fuji.git Vcs-Browser: https://anonscm.debian.org/gitweb/?p=collab-maint/fuji.git;a=summary diff -Nru fuji-0.3.0/debian/patches/fix_function_name fuji-1.0.2/debian/patches/fix_function_name --- fuji-0.3.0/debian/patches/fix_function_name 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/debian/patches/fix_function_name 2016-06-30 09:45:32.000000000 +0000 @@ -0,0 +1,15 @@ +# Please see igolang-github-shirou-gopsutil/v2migration.sh + +diff --git a/device/status.go b/device/status.go +index e3384e7..db0a2f3 100644 +--- a/device/status.go ++++ b/device/status.go +@@ -69,7 +69,7 @@ func (device Status) String() string { + func (c CPUStatus) Get() []message.Message { + ret := []message.Message{} + +- cpuTimes, err := cpu.CPUTimes(false) ++ cpuTimes, err := cpu.Times(false) + if err == nil { + for _, t := range c.CpuTimes { + msg := message.Message{ diff -Nru fuji-0.3.0/debian/patches/fix_path_of_paho fuji-1.0.2/debian/patches/fix_path_of_paho --- fuji-0.3.0/debian/patches/fix_path_of_paho 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/debian/patches/fix_path_of_paho 2016-06-30 09:40:38.000000000 +0000 @@ -0,0 +1,13 @@ +diff --git a/broker/broker.go b/broker/broker.go +index f2134bf..cc9d0c4 100644 +--- a/broker/broker.go ++++ b/broker/broker.go +@@ -25,7 +25,7 @@ import ( + "strings" + + log "github.com/Sirupsen/logrus" +- MQTT "github.com/eclipse/paho.mqtt.golang" ++ MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" + validator "gopkg.in/validator.v2" + + "github.com/shiguredo/fuji/config" diff -Nru fuji-0.3.0/debian/patches/remove_test fuji-1.0.2/debian/patches/remove_test --- fuji-0.3.0/debian/patches/remove_test 2016-02-26 15:17:05.000000000 +0000 +++ fuji-1.0.2/debian/patches/remove_test 2016-07-15 04:06:42.000000000 +0000 @@ -1,10 +1,36 @@ +diff --git a/tests/connect.toml b/tests/connect.toml +deleted file mode 100644 +index d3aa5a1..0000000 +--- a/tests/connect.toml ++++ /dev/null +@@ -1,20 +0,0 @@ +-[gateway] +- +- name = "hamlocalconnect" +- +-[[broker."mosquitto/1"]] +- +- host = "localhost" +- port = 1883 +- +- retry_interval = 10 +- +- +-[device."dora"] +- +- type = "dummy" +- broker = "mosquitto" +- qos = 0 +- +- interval = 10 +- payload = "connect local pub only Hello world." diff --git a/tests/connect_test.go b/tests/connect_test.go deleted file mode 100644 -index 05310b7..0000000 +index 673c74a..0000000 --- a/tests/connect_test.go +++ /dev/null -@@ -1,107 +0,0 @@ --// Copyright 2015 Shiguredo Inc. +@@ -1,104 +0,0 @@ +-// Copyright 2015-2016 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. @@ -25,23 +51,24 @@ - "testing" - "time" - -- MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" +- MQTT "github.com/eclipse/paho.mqtt.golang" - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji" - "github.com/shiguredo/fuji/broker" +- "github.com/shiguredo/fuji/config" - "github.com/shiguredo/fuji/device" - "github.com/shiguredo/fuji/gateway" -- "github.com/shiguredo/fuji/inidef" -) - -// publish test to broker on localhost -// dummydevice is used as a source of published message -func TestConnectLocalPub(t *testing.T) { - -- go fuji.Start("connectlocalpub.ini") +- go fuji.Start("connect.toml") - - time.Sleep(2 * time.Second) +- return -} - -// TestConnectLocalPubSub tests @@ -56,7 +83,7 @@ - // publised messages confirmed by subscriber - - // get config -- conf, err := inidef.LoadConfig("connectlocalpubsub.ini") +- conf, err := config.LoadConfig("connect.toml") - assert.Nil(err) - - // get Gateway @@ -68,7 +95,7 @@ - assert.Nil(err) - - // get DummyDevice -- dummyDevice, err := device.NewDummyDevice(conf.Sections[3], brokerList, device.NewDeviceChannel()) +- dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, device.NewDeviceChannel()) - assert.Nil(err) - assert.NotNil(dummyDevice) - @@ -79,11 +106,8 @@ - opts := MQTT.NewClientOptions() - url := fmt.Sprintf("tcp://%s:%d", brokerList[0].Host, brokerList[0].Port) - opts.AddBroker(url) -- opts.SetClientID(gw.Name) +- opts.SetClientID(fmt.Sprintf("prefix%s", gw.Name)) - opts.SetCleanSession(false) -- opts.SetDefaultPublishHandler(func(client *MQTT.Client, msg MQTT.Message) { -- subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} -- }) - - client := MQTT.NewClient(opts) - assert.Nil(err) @@ -92,101 +116,848 @@ - } - - qos := 0 -- topic := "#" -- client.Subscribe(topic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { +- expectedTopic := fmt.Sprintf("/%s/%s/%s/publish", gw.Name, dummyDevice.Name, dummyDevice.Type) +- expectedMessage := fmt.Sprintf("%s", dummyDevice.Payload) +- fmt.Printf("expetcted topic: %s\nexpected message%s", expectedTopic, expectedMessage) +- client.Subscribe(expectedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { +- subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} - }) - -- // TODO: should be write later -- /* -- channel := fuji.SetupMQTTChannel(client, gateway, brokerList[0]) +- // wait for 1 publication of dummy worker +- select { +- case message := <-subscriberChannel: +- assert.Equal(expectedTopic, message[0]) +- assert.Equal(expectedMessage, message[1]) +- case <-time.After(time.Second * 11): +- assert.Equal("subscribe completed in 11 sec", "not completed") +- } +- +- client.Disconnect(20) +-} +diff --git a/tests/mosquitto/ca.key b/tests/mosquitto/ca.key +deleted file mode 100644 +index bc2eadc..0000000 +--- a/tests/mosquitto/ca.key ++++ /dev/null +@@ -1,18 +0,0 @@ +------BEGIN RSA PRIVATE KEY----- +-Proc-Type: 4,ENCRYPTED +-DEK-Info: DES-EDE3-CBC,965D3104A27A8D8D +- +-+Ek6vaIgZA4wsEcQkzBonm+GXj2yqpn6mLXcXngEp/Z/qYJ/u9zbwiTl6mDsov4M +-4FB8qyycIOHmwnmHWNwel/YqUb5i6GYc9eeT3DPE2zgNIUb/hybsEg5j1ux9GU/P +-OIrC1bf1Kx+P+S+1Cfy3xCLxwpgr/XUVAlREWgqIDDqoK0paZQm3FLgYyy3Q1efU +-IeChXRWi4wYnugPhNSPqr+ZYBTxIbPZwSjk4HnSgXdPkE2ltgfeuDXvM4QYcB04Y +-GnHQ7b39wFkb9CUDjZyKQGWx6IN7bTO3TV0aarHnbzwN8doB49ovQZta88kTd99x +-8qgKc5ha5uq4YstjcBBVhraG1ZsJi/pg2OdP42N0N5ccWu2QFut28uLlMoBUX6PE +-Tw8Bub7AdDpJCVIJo5QzRx4+xhs4EfHUjTbq0R9ZE09qaVBQ1UlG6VMKF5sgrraw +-JEQ/cGDM/r84+E3NwLuLJF6fjYooYKgcPu3hVpfjWEK8QanAVNiBo7Uoq5126NLE +-fIkPwfnALCLCBzV2N5Yfk1zM4F9d03+PaN4EPrB4dfwoew7zKdXW7AwmEcVT7Z20 +-rLTndsjnVkn+7AObaftPB7ex/4uAS8NX0l8Si6o25oQVopU70/FSG4vyESfm4nEl +-7aOVOPc9hTdNmHwrwBm92DeTYZC9ZyQ5ofomJW6ZQbhzTYwIsxOf/a5+FIo+HtNs +-qLel6I/x8Vd+TN5dwujDkX21pN1jsF/MmrlSDLd09p9jmS0/pK86xy+hrazIbLU5 +-oqyvO5OmIUF3GSOGQnKn9C5kDykXsU1vMweeTJhr2iRRXs1VUhX5Pw== +------END RSA PRIVATE KEY----- +diff --git a/tests/mosquitto/ca.pem b/tests/mosquitto/ca.pem +deleted file mode 100644 +index 661effa..0000000 +--- a/tests/mosquitto/ca.pem ++++ /dev/null +@@ -1,17 +0,0 @@ +------BEGIN CERTIFICATE----- +-MIICqjCCAhOgAwIBAgIJAKk2CA51YCAVMA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV +-BAYTAkpQMRMwEQYDVQQIEwpTb21lLVN0YXRlMRAwDgYDVQQKEwdTb21lT3JnMQ0w +-CwYDVQQDEwRyb290MB4XDTE1MTExNjA4MDExMloXDTI1MTExMzA4MDExMlowQzEL +-MAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUxEDAOBgNVBAoTB1NvbWVP +-cmcxDTALBgNVBAMTBHJvb3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMlL +-Gg9sSZzqwNYJxM1+DQ4rkuLQuXg4HOAc6r1d+64PXShroAn+HemJuXP/Z4rInwIj +-LYbhYGU1AkCoX/776U61DEAkrioNWdvV3OZiwdgmLL+1tkjQC4QuineRy9xn49N0 +-qr2a6qV0gkz4ZM4WnKaGRiLOSyCI5rhagAVLwoFNAgMBAAGjgaUwgaIwHQYDVR0O +-BBYEFN7Iif0cRQiYVoWbXhqKI5LkkxGYMHMGA1UdIwRsMGqAFN7Iif0cRQiYVoWb +-XhqKI5LkkxGYoUekRTBDMQswCQYDVQQGEwJKUDETMBEGA1UECBMKU29tZS1TdGF0 +-ZTEQMA4GA1UEChMHU29tZU9yZzENMAsGA1UEAxMEcm9vdIIJAKk2CA51YCAVMAwG +-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAwn+DC1gG+O+oTGP4hJESOm6f +-IkTYSx4jmyuKqcR6VhLgX3H8bUHyH/B3Oqi8cnhgIhPq+6wf6jyV3KaUio46Jl7E +-hG2z3Rz9ZHgBrDrxvkR55ZTOFOf0FCSduxErnWKPllQCOzzLcZEuZAWvRKTM3NQw +-XB+OQcJgenRLw9n9cb4= +------END CERTIFICATE----- +diff --git a/tests/mosquitto/client.csr b/tests/mosquitto/client.csr +deleted file mode 100644 +index 84a6dc7..0000000 +--- a/tests/mosquitto/client.csr ++++ /dev/null +@@ -1,16 +0,0 @@ +------BEGIN CERTIFICATE REQUEST----- +-MIIClTCCAX0CAQAwUDELMAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUx +-GTAXBgNVBAoTEFNPTUVPUkdBTklaQVRJT04xETAPBgNVBAMTCHVzZXJuYW1lMIIB +-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuRBC17Y+/rgQMagOGqCdH58J +-LNv59R8HFHKiawvNJavtwEJRqfLytRwtyXjxalUOe7GlwvBAKiG/h7xE9HqoZzgs +-DWYyAEgAyedHxcoGg7ekRBTXUpkLxhxdCJBuUm26WN8PS0VdiCcqXBU5NH0DYPMX +-3OCl+Qdf+qEc+2yvN6fJC2up1gJ+FgufC2jaq8zwE77tBEZmWS/r3nk0EO2XFQ/Z +-Csz4XOrrKIX3Yq3r3BxWfQh/9ek7Zg0jqj1jjg4spAvsg9qjbfbE5BM/58XZ7EiS +-wht/1pMau6pgfEC8obfJU5AbiWrlXP6ERZQqpwbfkKorNnp/bw0EgiszT92y5wID +-AQABoAAwDQYJKoZIhvcNAQELBQADggEBAJlzPonKVkhimeMMwpJViHGtOlDOmcrT +-0hZIVGh95om4nmz6KcjvnRgHeb/XhgHkbtzOJW6DwxgYA/BGQHEGl/XAVAb5XIgG +-P8VN4U5U34dwzJaENuMbJtjx2U5+ZADfRLnj6foTd2vz/pyTfwUixX9rKMQRsgbV +-AU4FfEqpqgkh1WckSTgIlP3YaWJhJmgetNSxdFCa36YOhPztEqCRJEKopBXCwupX +-mGsdWjWkVyRqhFTjn2M82YKyp+WJGNYwva6akOfeWn0oJ4QchaMJG4s/WvGSP6TN +-y2ikm4462WBsbflIdF2c0N0UXScNyHBko0DpGNKzbQC0C2mbETeiguo= +------END CERTIFICATE REQUEST----- +diff --git a/tests/mosquitto/client.key b/tests/mosquitto/client.key +deleted file mode 100644 +index 9ee7edd..0000000 +--- a/tests/mosquitto/client.key ++++ /dev/null +@@ -1,27 +0,0 @@ +------BEGIN RSA PRIVATE KEY----- +-MIIEpAIBAAKCAQEAuRBC17Y+/rgQMagOGqCdH58JLNv59R8HFHKiawvNJavtwEJR +-qfLytRwtyXjxalUOe7GlwvBAKiG/h7xE9HqoZzgsDWYyAEgAyedHxcoGg7ekRBTX +-UpkLxhxdCJBuUm26WN8PS0VdiCcqXBU5NH0DYPMX3OCl+Qdf+qEc+2yvN6fJC2up +-1gJ+FgufC2jaq8zwE77tBEZmWS/r3nk0EO2XFQ/ZCsz4XOrrKIX3Yq3r3BxWfQh/ +-9ek7Zg0jqj1jjg4spAvsg9qjbfbE5BM/58XZ7EiSwht/1pMau6pgfEC8obfJU5Ab +-iWrlXP6ERZQqpwbfkKorNnp/bw0EgiszT92y5wIDAQABAoIBAHJ4pn/70PeKLyoo +-A6Fg3A/lNa2z2+dNa/mv9ts0D49Py95yp0TybEKuzXuj/eCCAFVuy1PLfEUTXv+8 +-6wI2pNhEHKulHSSjZSl+kBy+HE15WHhsU8xZsri2bq2PeU4vZWb3guRSYcqIP2F6 +-F0pqUZ60f3w20TM65pmG8wBqd+96Igb4pU2h+ZerqqEHxwt7lN7aSjgRiD0jEK+N +-PeeXHVVLuXVwL8zlPScZMCh64RXtkyJ1/a9+9U60LYWjuYs8IGrGBsX2rizbqi7L +-OjeZ6jO4IvlCBruLMMJ4aoUf+OgIlSoqfcpZ5KlY0D3W3vlXTpAYrG+kRTYTqpbc +-fOastgECgYEA5AkVExYsLGXbOJaDb+Ptkx3YtXPQkHe3xVYc4jxC5DR0zSThixIC +-S+KL0B2vfhZy9SCdSOJ/F+/lAs0InNsP/G2oF0cuop1rQdn3GAbOiyiASvjL8PnP +-LUmQhEburxfsfam3OZFwKGveNqA/pCkoQ98eBx7QMbWq59C2Cuw8rWcCgYEAz8If +-V8yPblxhVw5cu8HU086prJFIZyksyaWWUhP84IuZJa52hvzy8M+xostSQfc7D+V/ +-w3AKNSiSuabgSSmN0f+pLNosSVb36N+QFNCPBaBDqOP97fuIZlslCBaWm+etVE90 +-oAJDKllNglWm/rQwoPoJWklME9aNpNe1HkPd3oECgYEAs3jieU8uHRNdYkAz2lBN +-n0gSU11/fPR8Unff67759pnCg+LPEKFv5UG8QGPcxyPr/jlZERASb0iDuZyddraC +-8m1rqkZ/0cSLshxWeTaCQMvzjQ4blOFHyaDoePNKz8vIeW6lok1xNJ8RGXUuIYmz +-AxgLjhcWTMlqZWDCpf4gE2kCgYEAx5hl6EHcYlhaI/rmWHOldj+LfwCsoH9MSgXN +-XtlZDpjO7wanVJRbCcNfk1jmk/1jPqhrkGVpSRzLqZSK0X8cgu2tqCuKdIMa9R0j +-HPwpC2ym0/EFmccXic5yy0x4MRvox6D2GGtT/7F/54FGSFjwhxbwOU9FyaFMv1uE +-46ir1QECgYB0KnNQI4OLffaxnod8qsrSIC4muaXn3AFIKz76isQ5L6VSh+SZVHFe +-0P6q6XURsmlD8hZwdMMYN1OV0k9lrI2F5KeGs9B28P1RTM3cN5PhYgmVf3HNQU4N +-qcJW6ilH/dpBsyw7v5zrV5+MCDKiHPq0HGBn+Ea6vM7XxSJP3wE0jQ== +------END RSA PRIVATE KEY----- +diff --git a/tests/mosquitto/client.pem b/tests/mosquitto/client.pem +deleted file mode 100644 +index 2dfed47..0000000 +--- a/tests/mosquitto/client.pem ++++ /dev/null +@@ -1,16 +0,0 @@ +------BEGIN CERTIFICATE----- +-MIICjjCCAfcCCQC25uKBpE2iKzANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJK +-UDETMBEGA1UECBMKU29tZS1TdGF0ZTEQMA4GA1UEChMHU29tZU9yZzENMAsGA1UE +-AxMEcm9vdDAeFw0xNTExMTYwODA3NDlaFw0xNjExMTUwODA3NDlaMFAxCzAJBgNV +-BAYTAkpQMRMwEQYDVQQIEwpTb21lLVN0YXRlMRkwFwYDVQQKExBTT01FT1JHQU5J +-WkFUSU9OMREwDwYDVQQDEwh1c2VybmFtZTCCASIwDQYJKoZIhvcNAQEBBQADggEP +-ADCCAQoCggEBALkQQte2Pv64EDGoDhqgnR+fCSzb+fUfBxRyomsLzSWr7cBCUany +-8rUcLcl48WpVDnuxpcLwQCohv4e8RPR6qGc4LA1mMgBIAMnnR8XKBoO3pEQU11KZ +-C8YcXQiQblJtuljfD0tFXYgnKlwVOTR9A2DzF9zgpfkHX/qhHPtsrzenyQtrqdYC +-fhYLnwto2qvM8BO+7QRGZlkv6955NBDtlxUP2QrM+Fzq6yiF92Kt69wcVn0If/Xp +-O2YNI6o9Y44OLKQL7IPao232xOQTP+fF2exIksIbf9aTGruqYHxAvKG3yVOQG4lq +-5Vz+hEWUKqcG35CqKzZ6f28NBIIrM0/dsucCAwEAATANBgkqhkiG9w0BAQUFAAOB +-gQAWajbip5KzoaxcbT7N5SYPDjLC8eoTxHQkwUPhiPSGMhHxWyGR9Z2LfD05EAcR +-0ZFFWFm+InNizxJHPP5p2zA+1k0XdyphkHhVMPKT8XKj8+xMrNBPxflRiu0iDoO1 +-UJoNHHO7MxoLUYhLxHIyXUTeorvA2g5a6mYyPjeJ7wxorA== +------END CERTIFICATE----- +diff --git a/tests/mosquitto/mosquitto.conf b/tests/mosquitto/mosquitto.conf +deleted file mode 100644 +index 9e90405..0000000 +--- a/tests/mosquitto/mosquitto.conf ++++ /dev/null +@@ -1,21 +0,0 @@ +-user mosquitto +-log_dest file /mosquitto/mosquitto.log +-log_timestamp true +-log_type all +- +-listener 1883 +- +-listener 8883 +-cafile /mosquitto/ca.pem +-certfile /mosquitto/server.pem +-keyfile /mosquitto/server.key +-require_certificate false +- +-listener 9883 +-cafile /mosquitto/ca.pem +-certfile /mosquitto/server.pem +-keyfile /mosquitto/server.key +-require_certificate true +- +-listener 8080 +-protocol websockets +diff --git a/tests/mosquitto/server.csr b/tests/mosquitto/server.csr +deleted file mode 100644 +index 8c02ad2..0000000 +--- a/tests/mosquitto/server.csr ++++ /dev/null +@@ -1,16 +0,0 @@ +------BEGIN CERTIFICATE REQUEST----- +-MIIChTCCAW0CAQAwQDELMAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUx +-EDAOBgNVBAoTB1NvbWVPcmcxCjAIBgNVBAMUASowggEiMA0GCSqGSIb3DQEBAQUA +-A4IBDwAwggEKAoIBAQC3F7oL97GoSnwyWu3FNZGpJQhLhcHPqgSn7tH+mc6rcuYI +-zoaIob9A0Km1KC1g5XzE9DRmznwGDVyGtLbrtauELxVteJiESWOKb3T/D98ay09c +-ETz+EHDaUmVkKueQyZkUVTgJf0v/n+oSXF44CAZYFm89019qk6lt2XED9I2rCXl+ +-ngDQaN3HLcHyzEfNSkEqXX0R4W6UojuoCu27h8pCe1PEwuBzMM2NcTXg6abdxTRT +-Uy1r02PIQ2bpRRl5zGwJYzosw2LzfCNvy62JvMaxsW4aZhxKhFJ81U6uXCj2+bSI +-M16xGyZ5D4x58qO29McQZSWfUAhkhOpwkV9lTHAbAgMBAAGgADANBgkqhkiG9w0B +-AQsFAAOCAQEAKkmC35InxJ2s/jutm0fBmvdBcSZt/ta1qUrWq3wEVroJuEENb8G1 +-PZ86+dxxfenDw42Uj2vV/ndTVO6NBOEfxhu2fLlFdY8CL3z3R2UbSQ0AcRD4guKE +-PA4dTOiLJYi93ld2qgKb11tT7uysMCnhDcgl2zoCZcqaTM+0QryQsC1i/pPkT6yP +-ulikkel/28bz0+Wgi9lUltlF3lRfk3EwBqdZggX4YdEyzq6IfRYo5JyDNQ5t4NAX +-2mbYhBuwCZY4LFCARuvum2AWctTfCVdDMlkV99RKobh0aTCozD9Qbp4tjvcdN63b +-fMWP0yZS0vwinPzmP+aOl06YcNibqFyebA== +------END CERTIFICATE REQUEST----- +diff --git a/tests/mosquitto/server.key b/tests/mosquitto/server.key +deleted file mode 100644 +index d9d2eba..0000000 +--- a/tests/mosquitto/server.key ++++ /dev/null +@@ -1,27 +0,0 @@ +------BEGIN RSA PRIVATE KEY----- +-MIIEowIBAAKCAQEAtxe6C/exqEp8MlrtxTWRqSUIS4XBz6oEp+7R/pnOq3LmCM6G +-iKG/QNCptSgtYOV8xPQ0Zs58Bg1chrS267WrhC8VbXiYhEljim90/w/fGstPXBE8 +-/hBw2lJlZCrnkMmZFFU4CX9L/5/qElxeOAgGWBZvPdNfapOpbdlxA/SNqwl5fp4A +-0Gjdxy3B8sxHzUpBKl19EeFulKI7qArtu4fKQntTxMLgczDNjXE14Omm3cU0U1Mt +-a9NjyENm6UUZecxsCWM6LMNi83wjb8utibzGsbFuGmYcSoRSfNVOrlwo9vm0iDNe +-sRsmeQ+MefKjtvTHEGUln1AIZITqcJFfZUxwGwIDAQABAoIBAQCxgJ8t2wSxUwT1 +-DJJXDogYo35XOWWcHghFhpKvcg2aydmZ0B89dxIjlCfzKPBVcCZ2CwqCYMx8UZfS +-QIDWI1oU3FC5wKCcH0oRe9zBKnHxWAmoCE5JQUcnYZpKcg3toIR34eZhzrevKymS +-g1oUmDMOUzGljraCbIVlqdiXLQ/rL67OKHFZP4qEbCqEv8eIBEKMAL7E7S6PAuqa +-gMCter26fMvEJADheBIyqTc63Pz/XJIJCLFdySl3WYv69IHnLcXB/oQngo/anjb2 +-LbDwxyxZfkiJWfEa8RtL2qWoOsrfuzGICEz0TG6gA+5ZIW9hmrihI/fh7QKvtEJD +-/+EqgogBAoGBAOzf9lfVqe9j2VK6KkQUgdjp9JrtyCbyI8ooEToXuEmwjFz9vwyi +-pEJgzNvorHZrGZ+pmUg12R877g6WcYOxW9dnGR/LDdcE9cjfUYt3104sE212z1SC +-2lOywhrmGwlG/jkS/tK4WrLm8jBNEaxA4vB6VvVI1WLiBb6+3SQMzsHBAoGBAMXg +-H+TMY+NZHfa6XT4pjaKHcIL22+SQTuRkJOoOt0gj2GAMgwBW7WxhVJDAIqlWyCJW +-+KUKKW29o4fRX7/2RwLwRxzfIrmFg+XL1TJi5jEGYVSb+MsMUBpDw/c8W7x+guxT +-xYOKSAO78ZfiSncoqwk1sL09Ya3W20lhXngpOLDbAoGAUP2itRWRLRDu1aJhoTWB +-0DDuOarjrK1OH2jjuwExOcDrvT/leuSBVVDTur0rerHT6QuMJWyD+HH9S2+VEHor +-9NKDfKNo8AP6Jdx1fUJUk53uZpcg/Lxg+g084QWcaOelNM6R4mq2WEUuueUgDc2B +-yseJxARLMawmWrnX0uOuLgECgYBh1Y2PX2sn1kEVY1GE0aDAsjxz1EAmgx8ul0EV +-JI+EMIzj+Guw+EnNY1Yfd4/rsAelyuCHIT4Yj0HSfjfcPpUfo9NVOBIALj5nmN9h +-WTq9FI18+t0I756PTeAPVp141gg/dq/aeL1gc0VhNjZhMg9Wr2AiQL4R6IBliKnf +-uWnZLwKBgHfyg1w+dEUN/WDqJiRAxXkssgACrndXn/2eWbntKOkyO7Ux2HOTPtwg +-EofsDDa6Ltln9irqhbsjj2HLCWhF33OioqtWjWYfw66swfmH7qM/iZ+6pTKnsqdx +-VvtEEP0chZPhJI6CLIfIBQ3CDdBSrY1RY1E6b7csYQz9jfU6aq5T +------END RSA PRIVATE KEY----- +diff --git a/tests/mosquitto/server.pem b/tests/mosquitto/server.pem +deleted file mode 100644 +index 302a451..0000000 +--- a/tests/mosquitto/server.pem ++++ /dev/null +@@ -1,16 +0,0 @@ +------BEGIN CERTIFICATE----- +-MIICfjCCAecCCQC25uKBpE2iKjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJK +-UDETMBEGA1UECBMKU29tZS1TdGF0ZTEQMA4GA1UEChMHU29tZU9yZzENMAsGA1UE +-AxMEcm9vdDAeFw0xNTExMTYwODA1MDBaFw0yNTExMTMwODA1MDBaMEAxCzAJBgNV +-BAYTAkpQMRMwEQYDVQQIEwpTb21lLVN0YXRlMRAwDgYDVQQKEwdTb21lT3JnMQow +-CAYDVQQDFAEqMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtxe6C/ex +-qEp8MlrtxTWRqSUIS4XBz6oEp+7R/pnOq3LmCM6GiKG/QNCptSgtYOV8xPQ0Zs58 +-Bg1chrS267WrhC8VbXiYhEljim90/w/fGstPXBE8/hBw2lJlZCrnkMmZFFU4CX9L +-/5/qElxeOAgGWBZvPdNfapOpbdlxA/SNqwl5fp4A0Gjdxy3B8sxHzUpBKl19EeFu +-lKI7qArtu4fKQntTxMLgczDNjXE14Omm3cU0U1Mta9NjyENm6UUZecxsCWM6LMNi +-83wjb8utibzGsbFuGmYcSoRSfNVOrlwo9vm0iDNesRsmeQ+MefKjtvTHEGUln1AI +-ZITqcJFfZUxwGwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAKEE6zsYjrvl4MTAyx7f +-aV0upT+aqHaxBUPH4RkhHxWOqz6Ov9Xk06rafPh0ujry5IMPyFJ9Hi9UrFHoOMtB +-UUtdWe6whJUZhRSj+HSak1yCverLC/10jHfcqo2KnBrY1h+RIY2LcmspRayxe+Yj +-FAIihOL+maxgu5vlrrE3fmjG +------END CERTIFICATE----- +diff --git a/tests/retain_test.go b/tests/retain_test.go +deleted file mode 100644 +index a85efc8..0000000 +--- a/tests/retain_test.go ++++ /dev/null +@@ -1,225 +0,0 @@ +-// Copyright 2015-2016 Shiguredo Inc. +-// +-// Licensed under the Apache License, Version 2.0 (the "License"); +-// you may not use this file except in compliance with the License. +-// You may obtain a copy of the License at +-// +-// http://www.apache.org/licenses/LICENSE-2.0 +-// +-// Unless required by applicable law or agreed to in writing, software +-// distributed under the License is distributed on an "AS IS" BASIS, +-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-// See the License for the specific language governing permissions and +-// limitations under the License. +- +-package main +- +-import ( +- "fmt" +- "testing" +- "time" +- +- MQTT "github.com/eclipse/paho.mqtt.golang" +- "github.com/stretchr/testify/assert" +- +- "github.com/shiguredo/fuji" +- "github.com/shiguredo/fuji/broker" +- "github.com/shiguredo/fuji/config" +- "github.com/shiguredo/fuji/device" +- "github.com/shiguredo/fuji/gateway" +-) +- +-// TestRetainJustPublish tests +-// 1. connect gateway to local broker +-// 2. send data with retaind flag dummy device normaly +-func TestRetainJustPublish(t *testing.T) { +- assert := assert.New(t) - -- // Setup DummyDevice to publish test payload +- configStr := ` +- [gateway] +- +- name = "retainham" +- +- [[broker."local/1"]] +- +- host = "localhost" +- port = 1883 +- +- [device."doraretain"] +- +- type = "dummy" +- broker = "local" +- qos = 0 +- +- interval = 10 +- payload = "Hello world retain true." +- retain = true +-` - -- dummyDevice.Start(channel) +- conf, err := config.LoadConfigByte([]byte(configStr)) +- assert.Nil(err) - -- // wait for 1 publication of dummy worker -- message := <-subscriberChannel -- assert.Equal("dummy", message) +- commandChannel := make(chan string) +- go fuji.StartByFileWithChannel(conf, commandChannel) - -- client.Disconnect(250) -- */ +- time.Sleep(2 * time.Second) -} -diff --git a/tests/connectlocalpub.ini b/tests/connectlocalpub.ini +- +-// TestRetainSubscribePublishClose +-// 1. connect gateway to local broker +-// 2. send data with retaind flag from dummy device +-// 3. disconnect +-// 4. reconnect +-// 5. subscirbe and receive data +-func TestRetainSubscribePublishClose(t *testing.T) { +- assert := assert.New(t) +- configStr := ` +- [gateway] +- +- name = "testRetainafterclose" +- +- [[broker."local/1"]] +- +- host = "localhost" +- port = 1883 +- +- [device."dora"] +- +- type = "dummy" +- broker = "local" +- qos = 0 +- +- interval = 10 +- payload = "Hello retained world to subscriber after close." +- +- retain = true +-` +- conf, err := config.LoadConfigByte([]byte(configStr)) +- assert.Nil(err) +- isRetain := true +- generalPubSubTest(t, conf, isRetain) +-} +- +-// TestNoRetainSubscribePublishClose +-// 1. connect gateway to local broker +-// 2. send data without retaind flag from dummy device +-// 3. disconnect +-// 4. reconnect +-// 5. subscirbe and receive data +-func TestNoRetainSubscribePublishClose(t *testing.T) { +- assert := assert.New(t) +- configStr := ` +- [gateway] +- +- name = "testNoRetainafterclose" +- +- [[broker."local/1"]] +- +- host = "localhost" +- port = 1883 +- +- [device."dora"] +- +- type = "dummy" +- broker = "local" +- qos = 0 +- +- interval = 10 +- payload = "Hello retained world to subscriber after close." +-` +- conf, err := config.LoadConfigByte([]byte(configStr)) +- assert.Nil(err) +- isRetain := false +- generalPubSubTest(t, conf, isRetain) +-} +- +-func generalPubSubTest(t *testing.T, conf config.Config, isRetain bool) { +- assert := assert.New(t) +- +- commandChannel := make(chan string) +- go fuji.StartByFileWithChannel(conf, commandChannel) +- +- gw, err := gateway.NewGateway(conf) +- if err != nil { +- t.Error("Cannot make Gateway") +- } +- +- brokerList, err := broker.NewBrokers(conf, gw.BrokerChan) +- if err != nil { +- t.Error("Cannot make BrokerList") +- } +- +- devChan := device.NewDeviceChannel() +- gw.DeviceChannels = append(gw.DeviceChannels, devChan) +- dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, devChan) +- if err != nil { +- t.Error("Cannot make DummyDeviceList") +- } +- +- go func() { +- time.Sleep(2 * time.Second) +- +- // kill publisher +- gw.Stop() +- +- time.Sleep(2 * time.Second) +- +- subscriberChannel, err := setupRetainSubscriber(gw, brokerList[0], &dummyDevice) +- if err != config.Error("") { +- t.Error(err) +- } +- +- // check Retained message +- select { +- case retainedMessage := <-subscriberChannel: +- if !isRetain { +- assert.Equal("retained message arrived", "no retain message shall come") +- } +- retainedTopic := retainedMessage[0] +- retainedPayload := retainedMessage[1] +- +- expectedTopic := fmt.Sprintf("%s/%s/%s/%s/publish", brokerList[0].TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) +- expectedPayload := dummyDevice.Payload +- +- assert.Equal(expectedTopic, retainedTopic) +- assert.Equal(expectedPayload, retainedPayload) +- +- case <-time.After(time.Second * 2): +- if isRetain { +- assert.Equal("subscribe completed in 11 sec", "not completed") +- } +- } +- }() +- time.Sleep(5 * time.Second) +-} +- +-// setupRetainSubscriber returnes channel in order to read messages with retained flag +-func setupRetainSubscriber(gw *gateway.Gateway, broker *broker.Broker, dummyDevice *device.DummyDevice) (chan [2]string, config.Error) { +- // Setup MQTT pub/sub client to confirm published content. +- // +- messageOutputChannel := make(chan [2]string) +- +- opts := MQTT.NewClientOptions() +- brokerUrl := fmt.Sprintf("tcp://%s:%d", broker.Host, broker.Port) +- opts.AddBroker(brokerUrl) +- opts.SetClientID(gw.Name + "testSubscriber") // to distinguish MQTT client from publisher +- opts.SetCleanSession(false) +- opts.SetDefaultPublishHandler(func(client *MQTT.Client, msg MQTT.Message) { +- messageOutputChannel <- [2]string{msg.Topic(), string(msg.Payload())} +- }) +- +- client := MQTT.NewClient(opts) +- if client == nil { +- return nil, config.Error("NewClient failed") +- } +- +- if token := client.Connect(); token.Wait() && token.Error() != nil { +- return nil, config.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) +- } +- qos := 0 +- retainedTopic := fmt.Sprintf("%s/%s/%s/%s/publish", broker.TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) +- client.Subscribe(retainedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { +- }) +- +- return messageOutputChannel, config.Error("") +-} +diff --git a/tests/testing_conf.toml b/tests/testing_conf.toml deleted file mode 100644 -index c11bae7..0000000 ---- a/tests/connectlocalpub.ini +index 48e9026..0000000 +--- a/tests/testing_conf.toml +++ /dev/null -@@ -1,21 +0,0 @@ +@@ -1,66 +0,0 @@ -[gateway] - -- name = ham +- name = "ham" +- max_retry_count = 30 - --[broker "mosquitto/1"] +-[[broker."sango/1"]] - -- host = localhost +- host = "192.0.2.10" - port = 1883 - +- username = "fuji-gw" +- password = "123" +- +- topic_prefix = "fuji-gw@example.com" - retry_interval = 10 - - --[device "dora/dummy"] +-[[broker."sango/2"]] +- +- host = "192.0.2.11" +- port = 1883 - -- broker = mosquitto +- username = "fuji-gw" +- password = 123 +- +- topic_prefix = "fuji-gw@example.com" +- retry_interval = 10 +- +-[[broker."akane"]] +- +- host = "192.0.2.20" +- port = 8883 +- tls = true +- cacert = "mosquitto/ca.pem" +- +- username = "fuji-gw" +- password = 456 +- +-[device."spam"] +- +- type = "serial" +- broker = "sango" - qos = 0 - +- serial = "/dev/tty.ble" +- baud = 9600 +- size = 4 +- +-[device."beacon"] +- +- type = "serial" +- broker = "sango" +- qos = 2 +- +- serial = "/dev/tty.enocean" +- baud = 115200 +- size = 8 +- +-[device."dora"] +- +- type = "dummy" +- broker = "sango" +- qos = 2 +- - interval = 10 -- payload = connect local pub only Hello world. +- payload = "Hello world." +diff --git a/tests/tls_clientcert_test.go b/tests/tls_clientcert_test.go +deleted file mode 100644 +index 8a7acc6..0000000 +--- a/tests/tls_clientcert_test.go ++++ /dev/null +@@ -1,138 +0,0 @@ +-// Copyright 2015-2016 Shiguredo Inc. +-// +-// Licensed under the Apache License, Version 2.0 (the "License"); +-// you may not use this file except in compliance with the License. +-// You may obtain a copy of the License at +-// +-// http://www.apache.org/licenses/LICENSE-2.0 +-// +-// Unless required by applicable law or agreed to in writing, software +-// distributed under the License is distributed on an "AS IS" BASIS, +-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-// See the License for the specific language governing permissions and +-// limitations under the License. +- +-package main +- +-import ( +- "fmt" +- "testing" +- "time" +- +- MQTT "github.com/eclipse/paho.mqtt.golang" +- "github.com/stretchr/testify/assert" +- +- "github.com/shiguredo/fuji" +- "github.com/shiguredo/fuji/broker" +- "github.com/shiguredo/fuji/config" +- "github.com/shiguredo/fuji/device" +- "github.com/shiguredo/fuji/gateway" +-) +- +-var tlsClientCertconfigStr = ` +-[gateway] +- +- name = "tlsccerthamlocalconnect" +- +-[[broker."mosquitto/1"]] +- +- host = "localhost" +- port = 9883 +- tls = true +- cacert = "mosquitto/ca.pem" +- client_cert = "mosquitto/client.pem" +- client_key = "mosquitto/client.key" +- +- retry_interval = 10 +- +- +-[device."dora"] +- type = "dummy" +- +- broker = "mosquitto" +- qos = 0 +- +- interval = 10 +- payload = "connect local pub only Hello world." +-` +- +-// TestTLSConnectLocalPub +-func TestTLSClientCertConnectLocalPub(t *testing.T) { +- assert := assert.New(t) +- +- conf, err := config.LoadConfigByte([]byte(tlsClientCertconfigStr)) +- assert.Nil(err) +- commandChannel := make(chan string) +- go fuji.StartByFileWithChannel(conf, commandChannel) +- time.Sleep(2 * time.Second) +- +-} +- +-// TestTLSConnectLocalPubSub +-// 1. connect gateway to local broker with TLS +-// 2. send data from dummy +-// 3. check subscribe +-func TestTLSClientCertConnectLocalPubSub(t *testing.T) { +- assert := assert.New(t) +- +- // pub/sub test to broker on localhost +- // dummydevice is used as a source of published message +- // publised messages confirmed by subscriber +- +- // get config +- conf, err := config.LoadConfigByte([]byte(tlsClientCertconfigStr)) +- assert.Nil(err) +- +- // get Gateway +- gw, err := gateway.NewGateway(conf) +- assert.Nil(err) +- +- // get Broker +- brokerList, err := broker.NewBrokers(conf, gw.BrokerChan) +- assert.Nil(err) +- +- // get DummyDevice +- dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, device.NewDeviceChannel()) +- assert.Nil(err) +- assert.NotNil(dummyDevice) +- +- // Setup MQTT pub/sub client to confirm published content. +- // +- subscriberChannel := make(chan [2]string) +- +- opts := MQTT.NewClientOptions() +- url := fmt.Sprintf("ssl://%s:%d", brokerList[0].Host, brokerList[0].Port) +- opts.AddBroker(url) +- opts.SetClientID(fmt.Sprintf("prefix%s", gw.Name)) +- opts.SetCleanSession(false) +- +- tlsConfig, err := broker.NewTLSConfig(brokerList[0]) +- assert.Nil(err) +- opts.SetTLSConfig(tlsConfig) +- +- client := MQTT.NewClient(opts) +- assert.Nil(err) +- if token := client.Connect(); token.Wait() && token.Error() != nil { +- assert.Nil(token.Error()) +- t.Log(token.Error()) +- } +- +- qos := 0 +- expectedTopic := fmt.Sprintf("/%s/%s/%s/publish", gw.Name, dummyDevice.Name, dummyDevice.Type) +- expectedMessage := fmt.Sprintf("%s", dummyDevice.Payload) +- t.Logf("expetcted topic: %s\nexpected message%s", expectedTopic, expectedMessage) +- client.Subscribe(expectedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { +- subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} +- }) +- +- // wait for 1 publication of dummy worker +- select { +- case message := <-subscriberChannel: +- assert.Equal(expectedTopic, message[0]) +- assert.Equal(expectedMessage, message[1]) +- case <-time.After(time.Second * 11): +- assert.Equal("subscribe completed in 11 sec", "not completed") +- } - -- type = EnOcean -diff --git a/tests/connectlocalpubsub.ini b/tests/connectlocalpubsub.ini +- client.Disconnect(20) +-} +diff --git a/tests/tls_connect_test.go b/tests/tls_connect_test.go deleted file mode 100644 -index acb61f6..0000000 ---- a/tests/connectlocalpubsub.ini +index a17cf7b..0000000 +--- a/tests/tls_connect_test.go +++ /dev/null -@@ -1,36 +0,0 @@ --; Copyright 2015 Shiguredo Inc. --; --; Licensed under the Apache License, Version 2.0 (the "License"); --; you may not use this file except in compliance with the License. --; You may obtain a copy of the License at --; --; http://www.apache.org/licenses/LICENSE-2.0 --; --; Unless required by applicable law or agreed to in writing, software --; distributed under the License is distributed on an "AS IS" BASIS, --; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --; See the License for the specific language governing permissions and --; limitations under the License. +@@ -1,136 +0,0 @@ +-// Copyright 2015-2016 Shiguredo Inc. +-// +-// Licensed under the Apache License, Version 2.0 (the "License"); +-// you may not use this file except in compliance with the License. +-// You may obtain a copy of the License at +-// +-// http://www.apache.org/licenses/LICENSE-2.0 +-// +-// Unless required by applicable law or agreed to in writing, software +-// distributed under the License is distributed on an "AS IS" BASIS, +-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-// See the License for the specific language governing permissions and +-// limitations under the License. +- +-package main - +-import ( +- "fmt" +- "testing" +- "time" +- +- MQTT "github.com/eclipse/paho.mqtt.golang" +- "github.com/stretchr/testify/assert" - +- "github.com/shiguredo/fuji" +- "github.com/shiguredo/fuji/broker" +- "github.com/shiguredo/fuji/config" +- "github.com/shiguredo/fuji/device" +- "github.com/shiguredo/fuji/gateway" +-) +- +-var configStr = ` -[gateway] - -- name = ham +- name = "hamlocalconnect" +- +-[[broker."mosquitto/1"]] +- +- host = "localhost" +- port = 8883 +- tls = true +- cacert = "mosquitto/ca.pem" +- +- retry_interval = 10 +- - --[broker "mosquitto/1"] +-[device."dora"] +- type = "dummy" +- +- broker = "mosquitto" +- qos = 0 +- +- interval = 10 +- payload = "connect local pub only Hello world." +-` +- +-// TestTLSConnectLocalPub +-func TestTLSConnectLocalPub(t *testing.T) { +- assert := assert.New(t) +- +- conf, err := config.LoadConfigByte([]byte(configStr)) +- assert.Nil(err) +- commandChannel := make(chan string) +- go fuji.StartByFileWithChannel(conf, commandChannel) +- time.Sleep(2 * time.Second) +- +-} +- +-// TestTLSConnectLocalPubSub +-// 1. connect gateway to local broker with TLS +-// 2. send data from dummy +-// 3. check subscribe +-func TestTLSConnectLocalPubSub(t *testing.T) { +- assert := assert.New(t) +- +- // pub/sub test to broker on localhost +- // dummydevice is used as a source of published message +- // publised messages confirmed by subscriber +- +- // get config +- conf, err := config.LoadConfigByte([]byte(configStr)) +- assert.Nil(err) +- +- // get Gateway +- gw, err := gateway.NewGateway(conf) +- assert.Nil(err) +- +- // get Broker +- brokerList, err := broker.NewBrokers(conf, gw.BrokerChan) +- assert.Nil(err) +- +- // get DummyDevice +- dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, device.NewDeviceChannel()) +- assert.Nil(err) +- assert.NotNil(dummyDevice) - -- host = localhost -- port = 1883 +- // Setup MQTT pub/sub client to confirm published content. +- // +- subscriberChannel := make(chan [2]string) - -- retry_interval = 10 +- opts := MQTT.NewClientOptions() +- url := fmt.Sprintf("ssl://%s:%d", brokerList[0].Host, brokerList[0].Port) +- opts.AddBroker(url) +- opts.SetClientID(fmt.Sprintf("prefix%s", gw.Name)) +- opts.SetCleanSession(false) - +- tlsConfig, err := broker.NewTLSConfig(brokerList[0]) +- assert.Nil(err) +- opts.SetTLSConfig(tlsConfig) - --[device "dora/dummy"] +- client := MQTT.NewClient(opts) +- assert.Nil(err) +- if token := client.Connect(); token.Wait() && token.Error() != nil { +- assert.Nil(token.Error()) +- t.Log(token.Error()) +- } - -- broker = mosquitto -- qos = 0 +- qos := 0 +- expectedTopic := fmt.Sprintf("/%s/%s/%s/publish", gw.Name, dummyDevice.Name, dummyDevice.Type) +- expectedMessage := fmt.Sprintf("%s", dummyDevice.Payload) +- t.Logf("expetcted topic: %s\nexpected message%s", expectedTopic, expectedMessage) +- client.Subscribe(expectedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { +- subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} +- }) - -- interval = 10 -- payload = connect local pubsub Hello world. +- // wait for 1 publication of dummy worker +- select { +- case message := <-subscriberChannel: +- assert.Equal(expectedTopic, message[0]) +- assert.Equal(expectedMessage, message[1]) +- case <-time.After(time.Second * 11): +- assert.Equal("subscribe completed in 11 sec", "not completed") +- } - -- type = EnOcean -diff --git a/tests/ini_retain_test.go b/tests/ini_retain_test.go +- client.Disconnect(20) +-} +diff --git a/tests/toml_retain_test.go b/tests/toml_retain_test.go deleted file mode 100644 -index 532c071..0000000 ---- a/tests/ini_retain_test.go +index 81a92df..0000000 +--- a/tests/toml_retain_test.go +++ /dev/null -@@ -1,186 +0,0 @@ --// Copyright 2015 Shiguredo Inc. +@@ -1,192 +0,0 @@ +-// Copyright 2015-2016 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. @@ -208,32 +979,33 @@ - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji/broker" +- "github.com/shiguredo/fuji/config" - "github.com/shiguredo/fuji/device" -- "github.com/shiguredo/fuji/inidef" - "github.com/shiguredo/fuji/message" -) - --// iniRetainTestCase はRetain機能のテストの条件を示すデータ型です。 --// iniString は設定ファイルの内容 --// expectedError はテストを実行したときに期待されるエラーの状態 --// message はテストが失敗した内容の説明 --type iniRetainTestCase struct { -- iniStr string -- expectedError inidef.AnyError +-// configRetainTestCase indicates a condition for testing Retain. +-// configString is the body of configuration file. +-// expectedError is the expected error state when the test is executed. +-// message is the detail of test failure. +-type configRetainTestCase struct { +- configStr string +- expectedError config.AnyError - message string -} - --var serialDeviceTestcases = []iniRetainTestCase{ +-var serialDeviceTestcases = []configRetainTestCase{ - // check device validation without retain flag - { -- iniStr: ` -- [broker "sango/1"] -- host = localhost +- configStr: ` +- [[broker."sango/1"]] +- host = "localhost" - port = 1883 - -- [device "hi/serial"] -- broker = sango -- serial = /dev/tty +- [device."hi"] +- type = "serial" +- broker = "sango" +- serial = "/dev/tty" - baud = 9600 - qos = 0 -`, @@ -241,95 +1013,98 @@ - message: "Retain flag could not be omitted. Shall be optional."}, - // check device validation with retain flag - { -- iniStr: ` -- [broker "sango/1"] -- host = localhost +- configStr: ` +- [[broker."sango/1"]] +- host = "localhost" - port = 1883 - -- [device "hi/serial"] -- broker = sango -- serial = /dev/tty +- [device."hi"] +- type = "serial" +- broker = "sango" +- serial = "/dev/tty" - baud = 9600 - qos = 0 - retain = true -- qos = 0 -`, - expectedError: nil, - message: "Retain flag could not be set."}, - // check device validation with retain flag is false - { -- iniStr: ` -- [broker "sango/1"] -- host = localhost +- configStr: ` +- [[broker."sango/1"]] +- host = "localhost" - port = 1883 - -- [device "hi/serial"] -- broker = sango -- serial = /dev/tty +- [device."hi"] +- type = "serial" +- broker = "sango" +- serial = "/dev/tty" - baud = 9600 - qos = 0 - retain = false -- qos = 0 -`, - expectedError: nil, - message: "Retain flag could not be un-set."}, -} - --var dummyDeviceTestcases = []iniRetainTestCase{ +-var dummyDeviceTestcases = []configRetainTestCase{ - // check device validation without retain flag - { -- iniStr: ` -- [broker "sango/1"] -- host = localhost +- configStr: ` +- [[broker."sango/1"]] +- host = "localhost" - port = 1883 - -- [device "hi/dummy"] -- broker = sango +- [device."hi"] +- type = "dummy" +- broker = "sango" - qos = 0 - interval = 10 -- payload = Hello world. +- payload = "Hello world." -`, - expectedError: nil, - message: "Retain flag could not be omitted. Shall be optional."}, - // check device validation with retain flag - { -- iniStr: ` -- [broker "sango/1"] -- host = localhost +- configStr: ` +- [[broker."sango/1"]] +- host = "localhost" - port = 1883 - -- [device "hi/dummy"] -- broker = sango +- [device."hi"] +- type = "dummy" +- broker = "sango" - qos = 0 - retain = true - interval = 10 -- payload = Hello world. +- payload = "Hello world." -`, - expectedError: nil, - message: "Retain flag could not be set."}, - // check device validation with retain flag is false - { -- iniStr: ` -- [broker "sango/1"] -- host = localhost +- configStr: ` +- [[broker."sango/1"]] +- host = "localhost" - port = 1883 - -- [device "hi/dummy"] -- broker = sango +- [device."hi"] +- type = "dummy" +- broker = "sango" - qos = 0 - retain = false - interval = 10 -- payload = Hello world. +- payload = "Hello world." -`, - expectedError: nil, - message: "Retain flag could not be un-set."}, -} - --// generalIniRetainSerialDeviceTest checks retain function with serial device --func generalIniRetainSerialDeviceTest(test iniRetainTestCase, t *testing.T) { +-// generalConfigRetainSerialDeviceTest checks retain function with serial device +-func generalConfigRetainSerialDeviceTest(test configRetainTestCase, t *testing.T) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfigByte([]byte(test.iniStr)) +- conf, err := config.LoadConfigByte([]byte(test.configStr)) - assert.Nil(err) - - brokers, err := broker.NewBrokers(conf, make(chan message.Message)) @@ -340,17 +1115,17 @@ - assert.Equal(1, len(devices)) -} - --// generalIniRetainDummyDeviceTest checks retain function with dummy device --func generalIniRetainDummyDeviceTest(test iniRetainTestCase, t *testing.T) { +-// generalConfigRetainDummyDeviceTest checks retain function with dummy device +-func generalConfigRetainDummyDeviceTest(test configRetainTestCase, t *testing.T) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfigByte([]byte(test.iniStr)) +- conf, err := config.LoadConfigByte([]byte(test.configStr)) - assert.Nil(err) - - brokers, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - -- dummy, err := device.NewDummyDevice(conf.Sections[2], brokers, device.NewDeviceChannel()) +- dummy, err := device.NewDummyDevice(conf.Sections[1], brokers, device.NewDeviceChannel()) - if test.expectedError == nil { - assert.Nil(err) - assert.NotNil(dummy) @@ -359,26 +1134,28 @@ - } -} - --// TestIniRetainDeviceAll tests a serial device using test code --func TestIniRetainDeviceAll(t *testing.T) { +-// TestConfigRetainDeviceAll tests a serial device using test code +-func TestConfigRetainDeviceAll(t *testing.T) { +- i := 0 - for _, testcase := range serialDeviceTestcases { -- generalIniRetainSerialDeviceTest(testcase, t) +- generalConfigRetainSerialDeviceTest(testcase, t) +- i++ - } -} - --// TestIniRetainDeviceAll tests a dummy device using test code --func TestIniRetainDummyDeviceAll(t *testing.T) { +-// TestConfigRetainDeviceAll tests a dummy device using test code +-func TestConfigRetainDummyDeviceAll(t *testing.T) { - for _, testcase := range dummyDeviceTestcases { -- generalIniRetainDummyDeviceTest(testcase, t) +- generalConfigRetainDummyDeviceTest(testcase, t) - } -} -diff --git a/tests/ini_test.go b/tests/ini_test.go +diff --git a/tests/toml_test.go b/tests/toml_test.go deleted file mode 100644 -index 62fd356..0000000 ---- a/tests/ini_test.go +index fa500b5..0000000 +--- a/tests/toml_test.go +++ /dev/null -@@ -1,78 +0,0 @@ --// Copyright 2015 Shiguredo Inc. +@@ -1,81 +0,0 @@ +-// Copyright 2015-2016 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. @@ -400,43 +1177,43 @@ - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji/broker" +- "github.com/shiguredo/fuji/config" - "github.com/shiguredo/fuji/device" - "github.com/shiguredo/fuji/gateway" -- "github.com/shiguredo/fuji/inidef" - "github.com/shiguredo/fuji/message" -) - --func TestIniLoadini(t *testing.T) { +-func TestLoadConfig(t *testing.T) { - assert := assert.New(t) - -- _, err := inidef.LoadConfig("testing_conf.ini") +- _, err := config.LoadConfig("testing_conf.toml") - assert.Nil(err) -} - --func TestIniNewGateway(t *testing.T) { +-func TestNewGateway(t *testing.T) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfig("testing_conf.ini") +- conf, err := config.LoadConfig("testing_conf.toml") - assert.Nil(err) - gw, err := gateway.NewGateway(conf) - assert.Nil(err) - assert.Equal("ham", gw.Name) -} - --func TestIniNewBrokers(t *testing.T) { +-func TestNewBrokers(t *testing.T) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfig("testing_conf.ini") +- conf, err := config.LoadConfig("testing_conf.toml") - assert.Nil(err) - brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - assert.Equal(3, len(brokerList)) -} - --func TestIniNewSerialDevices(t *testing.T) { +-func TestNewSerialDevices(t *testing.T) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfig("testing_conf.ini") +- conf, err := config.LoadConfig("testing_conf.toml") - brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - deviceList, _, err := device.NewDevices(conf, brokerList) @@ -444,25 +1221,28 @@ - assert.Equal(3, len(deviceList)) -} - --func TestIniNewDummyDevice(t *testing.T) { +-func TestNewDummyDevice(t *testing.T) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfig("testing_conf.ini") +- conf, err := config.LoadConfig("testing_conf.toml") - brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - -- dummy, err := device.NewDummyDevice(conf.Sections[7], brokerList, device.NewDeviceChannel()) +- section := config.SearchDeviceType(&conf.Sections, "dummy") +- assert.NotNil(section) +- +- dummy, err := device.NewDummyDevice(*section, brokerList, device.NewDeviceChannel()) - assert.Nil(err) - assert.Equal("dummy", dummy.DeviceType()) - assert.Equal(2, int(dummy.QoS)) -} -diff --git a/tests/ini_will_test.go b/tests/ini_will_test.go +diff --git a/tests/toml_will_test.go b/tests/toml_will_test.go deleted file mode 100644 -index 0687fc5..0000000 ---- a/tests/ini_will_test.go +index bc10c49..0000000 +--- a/tests/toml_will_test.go +++ /dev/null @@ -1,116 +0,0 @@ --// Copyright 2015 Shiguredo Inc. +-// Copyright 2015-2016 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. @@ -484,44 +1264,44 @@ - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji/broker" -- "github.com/shiguredo/fuji/inidef" +- "github.com/shiguredo/fuji/config" - "github.com/shiguredo/fuji/message" -) - --type iniWillTestCase struct { -- iniStr string // testcase config file -- expectedError inidef.AnyError // expected error status +-type configWillTestCase struct { +- configStr string // testcase config file +- expectedError config.AnyError // expected error status - message string // message when failed -} - --var testcases = []iniWillTestCase{ +-var testcases = []configWillTestCase{ - // tests broker validation without will_message - { -- iniStr: ` -- [broker "sango/1"] +- configStr: ` +- [[broker."sango/1"]] - -- host = localhost +- host = "localhost" - port = 1883 -`, - expectedError: nil, - message: "WillMessage could not be omitted. Shall be optional."}, - // tests broker validation with will_message - { -- iniStr: ` -- [broker "sango/1"] +- configStr: ` +- [[broker."sango/1"]] - -- host = localhost +- host = "localhost" - port = 1883 -- will_message = Hello world. +- will_message = "Hello world." -`, - expectedError: nil, - message: "WillMessage could not be defined."}, - // tests broker validation with empty will_message - { -- iniStr: ` -- [broker "sango/1"] +- configStr: ` +- [[broker."sango/1"]] - -- host = localhost +- host = "localhost" - port = 1883 - will_message = "" -`, @@ -529,43 +1309,43 @@ - message: "Empty WillMessage could not be defined."}, - // tests multiple broker validation with only one will_message - { -- iniStr: ` -- [broker "sango/1"] +- configStr: ` +- [[broker."sango/1"]] - -- host = localhost +- host = "localhost" - port = 1883 - -- [broker "sango/2"] +- [[broker."sango/2"]] - -- host = 192.168.1.1 +- host = "192.168.1.1 " - port = 1883 -- will_message = Hello world. +- will_message = "Hello world." -`, - expectedError: nil, - message: "WillMessage could not be defined for one of two."}, - // tests multiple broker validation with both will_message - { -- iniStr: ` -- [broker "sango/1"] +- configStr: ` +- [[broker."sango/1"]] - -- host = localhost +- host = "localhost" - port = 1883 -- will_message = Change the world. +- will_message = "Change the world." - -- [broker "sango/2"] +- [[broker."sango/2"]] - -- host = 192.168.1.1 +- host = "192.168.1.1" - port = 1883 -- will_message = Hello world. +- will_message = "Hello world." -`, - expectedError: nil, - message: "WillMessage could not be defined for both of two."}, -} - --func generalIniWillTest(test iniWillTestCase, t *testing.T) { +-func generalConfigWillTest(test configWillTestCase, t *testing.T) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfigByte([]byte(test.iniStr)) +- conf, err := config.LoadConfigByte([]byte(test.configStr)) - assert.Nil(err) - - brokers, err := broker.NewBrokers(conf, make(chan message.Message)) @@ -573,18 +1353,18 @@ - assert.NotEqual(0, len(brokers)) -} - --func TestIniWillAll(t *testing.T) { +-func TestConfigWillAll(t *testing.T) { - for _, testcase := range testcases { -- generalIniWillTest(testcase, t) +- generalConfigWillTest(testcase, t) - } -} -diff --git a/tests/retain_test.go b/tests/retain_test.go +diff --git a/tests/will_test.go b/tests/will_test.go deleted file mode 100644 -index b557a1c..0000000 ---- a/tests/retain_test.go +index cb87e81..0000000 +--- a/tests/will_test.go +++ /dev/null -@@ -1,172 +0,0 @@ --// Copyright 2015 Shiguredo Inc. +@@ -1,345 +0,0 @@ +-// Copyright 2015-2016 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. @@ -602,295 +1382,105 @@ - -import ( - "fmt" +- "os" +- "os/exec" +- "path/filepath" - "testing" - "time" - -- MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" +- MQTT "github.com/eclipse/paho.mqtt.golang" - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji" - "github.com/shiguredo/fuji/broker" -- "github.com/shiguredo/fuji/device" +- "github.com/shiguredo/fuji/config" - "github.com/shiguredo/fuji/gateway" -- "github.com/shiguredo/fuji/inidef" -) - --// TestRetainJustPublish tests --// 1. connect gateway to local broker --// 2. send data with retaind flag dummy device normaly --func TestRetainJustPublish(t *testing.T) { +-var tmpTomlName = ".tmp.toml" +- +-// TestWillJustPublish tests +-// 1. connect localhost broker with will message +-// 2. send data from a dummy device +-// 3. disconnect +-func TestWillJustPublish(t *testing.T) { - assert := assert.New(t) -- iniStr := ` +- +- configStr := ` - [gateway] -- -- name = retainham -- -- [broker "local/1"] -- -- host = localhost +- name = "willjustpublishham" +- [[broker."local/1"]] +- host = "localhost" - port = 1883 -- -- [device "doraretain/dummy"] -- -- broker = local +- will_message = "no letter is good letter." +- [device."dora"] +- type = "dummy" +- broker = "local" - qos = 0 -- - interval = 10 -- payload = Hello world retain true. -- -- type = EnOcean -- retain = true +- payload = "Hello will just publish world." -` -- conf, err := inidef.LoadConfigByte([]byte(iniStr)) +- conf, err := config.LoadConfigByte([]byte(configStr)) - assert.Nil(err) - commandChannel := make(chan string) - go fuji.StartByFileWithChannel(conf, commandChannel) +- time.Sleep(5 * time.Second) - -- time.Sleep(2 * time.Second) +- // fuji.Stop() -} - --// TestRetainSubscribePublishClose --// 1. connect gateway to local broker --// 2. send data with retaind flag from dummy device --// 3. disconnect --// 4. reconnect --// 5. subscirbe and receive data --func TestRetainSubscribePublishClose(t *testing.T) { +-// TestWillWithPrefixSubscribePublishClose +-// 1. connect subscriber and publisher to localhost broker with will message with prefixed topic +-// 2. send data from a dummy device +-// 3. force disconnect +-// 4. check subscriber does not receives will message immediately +-func TestWillWithPrefixSubscribePublishClose(t *testing.T) { - assert := assert.New(t) -- iniStr := ` +- +- configStr := ` - [gateway] -- -- name = testRetainafterclose -- -- [broker "local/1"] -- -- host = localhost +- name = "testprefixwill" +- [[broker."local/1"]] +- host = "localhost" - port = 1883 -- -- [device "dora/dummy"] -- -- broker = local +- will_message = "no letter is good letter." +- topic_prefix = "prefix" +- [device."dora"] +- type = "dummy" +- broker = "local" - qos = 0 -- - interval = 10 -- payload = Hello retained world to subscriber after close. -- -- type = EnOcean -- retain = true +- payload = "Hello will with prefix." -` -- commandChannel := make(chan string) -- conf, err := inidef.LoadConfigByte([]byte(iniStr)) -- assert.Nil(err) -- go fuji.StartByFileWithChannel(conf, commandChannel) -- -- gw, err := gateway.NewGateway(conf) -- if err != nil { -- t.Error("Cannot make Gateway") -- } -- -- brokerList, err := broker.NewBrokers(conf, gw.BrokerChan) -- if err != nil { -- t.Error("Cannot make BrokerList") -- } -- -- devChan := device.NewDeviceChannel() -- gw.DeviceChannels = append(gw.DeviceChannels, devChan) -- dummyDevice, err := device.NewDummyDevice(conf.Sections[3], brokerList, devChan) -- if err != nil { -- t.Error("Cannot make DummyDeviceList") -- } -- -- go func() { -- time.Sleep(2 * time.Second) -- -- // kill publisher -- gw.Stop() -- -- time.Sleep(2 * time.Second) -- -- subscriberChannel, err := setupRetainSubscriber(gw, brokerList[0], &dummyDevice) -- if err != inidef.Error("") { -- t.Error(err) -- } -- // check Retained message -- retainedMessage := <-subscriberChannel -- retainedTopic := retainedMessage[0] -- retainedPayload := retainedMessage[1] -- -- expectedTopic := fmt.Sprintf("%s/%s/%s/%s", brokerList[0].TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) -- expectedPayload := dummyDevice.Payload -- -- assert.Equal(expectedTopic, retainedTopic) -- assert.Equal(expectedPayload, retainedPayload) -- }() -- time.Sleep(5 * time.Second) --} -- --// setupRetainSubscriber returnes channel in order to read messages with retained flag --func setupRetainSubscriber(gw *gateway.Gateway, broker *broker.Broker, dummyDevice *device.DummyDevice) (chan [2]string, inidef.Error) { -- // Setup MQTT pub/sub client to confirm published content. -- // -- messageOutputChannel := make(chan [2]string) -- -- opts := MQTT.NewClientOptions() -- brokerUrl := fmt.Sprintf("tcp://%s:%d", broker.Host, broker.Port) -- opts.AddBroker(brokerUrl) -- opts.SetClientID(gw.Name + "testSubscriber") // to distinguish MQTT client from publisher -- opts.SetCleanSession(false) -- opts.SetDefaultPublishHandler(func(client *MQTT.Client, msg MQTT.Message) { -- messageOutputChannel <- [2]string{msg.Topic(), string(msg.Payload())} -- }) -- -- client := MQTT.NewClient(opts) -- if client == nil { -- return nil, inidef.Error("NewClient failed") -- } -- -- if token := client.Connect(); token.Wait() && token.Error() != nil { -- return nil, inidef.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) -- } -- qos := 0 -- retainedTopic := fmt.Sprintf("%s/%s/%s/%s", broker.TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) -- client.Subscribe(retainedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { -- }) -- -- return messageOutputChannel, inidef.Error("") +- expectedWill := true +- ok := genericWillTestDriver(t, configStr, "prefix/testprefixwill/will", []byte("no letter is good letter."), expectedWill) +- assert.True(ok, "Failed to receive Will with prefix message") -} -diff --git a/tests/testing_conf.ini b/tests/testing_conf.ini -deleted file mode 100644 -index bde5611..0000000 ---- a/tests/testing_conf.ini -+++ /dev/null -@@ -1,65 +0,0 @@ --[gateway] -- -- name = ham -- --[broker "sango/1"] -- -- host = 192.0.2.10 -- port = 1883 -- -- username = fuji-gw -- password = 123 -- -- topic_prefix = fuji-gw@example.com -- retry_interval = 10 -- -- --[broker "sango/2"] -- -- host = 192.0.2.11 -- port = 1883 -- -- username = fuji-gw -- password = 123 -- -- topic_prefix = fuji-gw@example.com -- retry_interval = 10 -- --[broker "akane"] -- -- host = 192.0.2.20 -- port = 8883 -- tls = true -- cert = /path/to/cert -- -- username = fuji-gw -- password = 456 -- --[device "spam/serial"] -- -- broker = sango -- qos = 0 -- -- serial = /dev/tty.ble -- baud = 9600 -- size = 4 -- type = BLE -- --[device "beacon/serial"] -- -- broker = sango -- qos = 2 -- -- serial = /dev/tty.enocean -- baud = 115200 -- size = 8 -- type = EnOcean -- --[device "dora/dummy"] -- -- broker = sango -- qos = 2 -- -- interval = 10 -- payload = Hello world. -- type = BLE -diff --git a/tests/will_test.go b/tests/will_test.go -deleted file mode 100644 -index 05651e6..0000000 ---- a/tests/will_test.go -+++ /dev/null -@@ -1,212 +0,0 @@ --// Copyright 2015 Shiguredo Inc. --// --// Licensed under the Apache License, Version 2.0 (the "License"); --// you may not use this file except in compliance with the License. --// You may obtain a copy of the License at --// --// http://www.apache.org/licenses/LICENSE-2.0 --// --// Unless required by applicable law or agreed to in writing, software --// distributed under the License is distributed on an "AS IS" BASIS, --// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --// See the License for the specific language governing permissions and --// limitations under the License. -- --package main - --import ( -- "fmt" -- "testing" -- "time" -- -- MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" -- "github.com/stretchr/testify/assert" -- -- "github.com/shiguredo/fuji" -- "github.com/shiguredo/fuji/broker" -- "github.com/shiguredo/fuji/gateway" -- "github.com/shiguredo/fuji/inidef" --) -- --// TestWillJustPublish tests --// 1. connect localhost broker with will message +-// TestNoWillSubscribePublishClose +-// 1. connect subscriber and publisher to localhost broker without will message -// 2. send data from a dummy device --// 3. disconnect --func TestWillJustPublish(t *testing.T) { +-// 3. force disconnect +-// 4. check subscriber does not receives will message immediately +-func TestNoWillSubscribePublishClose(t *testing.T) { - assert := assert.New(t) - -- iniStr := ` +- configStr := ` - [gateway] -- name = willjustpublishham -- [broker "local/1"] -- host = localhost +- name = "testnowillafterclose" +- [[broker."local/1"]] +- host = "localhost" - port = 1883 -- will_message = no letter is good letter. -- [device "dora/dummy"] -- broker = local +- [device."dora"] +- type = "dummy" +- broker = "local" - qos = 0 - interval = 10 -- payload = Hello will just publish world. -- type = EnOcean +- payload = "Hello will just publish world." -` -- conf, err := inidef.LoadConfigByte([]byte(iniStr)) -- assert.Nil(err) -- commandChannel := make(chan string) -- go fuji.StartByFileWithChannel(conf, commandChannel) -- time.Sleep(5 * time.Second) -- -- // fuji.Stop() +- expectedWill := false +- ok := genericWillTestDriver(t, configStr, "/testnowillafterclose/will", []byte(""), expectedWill) +- assert.False(ok, "Failed to receive Will message") -} - -// TestWillSubscribePublishClose @@ -901,21 +1491,22 @@ -func TestWillSubscribePublishClose(t *testing.T) { - assert := assert.New(t) - -- iniStr := ` +- configStr := ` - [gateway] -- name = testwillafterclose -- [broker "local/1"] -- host = localhost +- name = "testwillafterclose" +- [[broker."local/1"]] +- host = "localhost" - port = 1883 -- will_message = good letter is no letter. -- [device "dora/dummy"] -- broker = local +- will_message = "good letter is no letter." +- [device."dora"] +- type = "dummy" +- broker = "local" - qos = 0 - interval = 10 -- payload = Hello will just publish world. -- type = EnOcean +- payload = "Hello will just publish world." -` -- ok := genericWillTestDriver(t, iniStr, "/testwillafterclose/will", []byte("good letter is no letter.")) +- expectedWill := true +- ok := genericWillTestDriver(t, configStr, "/testwillafterclose/will", []byte("good letter is no letter."), expectedWill) - assert.True(ok, "Failed to receive Will message") -} - @@ -925,47 +1516,83 @@ -// 3. force disconnect -// 4. check subscriber receives will message -func TestWillSubscribePublishCloseEmpty(t *testing.T) { -- iniStr := ` +- configStr := ` - [gateway] -- name = testwillaftercloseemptywill -- [broker "local/1"] -- host = localhost +- name = "testwillaftercloseemptywill" +- [[broker."local/1"]] +- host = "localhost" - port = 1883 -- will_message = -- [device "dora/dummy"] -- broker = local +- will_message = "" +- [device."dora"] +- type = "dummy" +- broker = "local" - qos = 0 - interval = 10 -- payload = Hello will just publish world. -- type = EnOcean +- payload = "Hello will just publish world." -` -- ok := genericWillTestDriver(t, iniStr, "/testwillaftercloseemptywill/will", []byte{}) +- expectedWill := true +- ok := genericWillTestDriver(t, configStr, "/testwillaftercloseemptywill/will", []byte{}, expectedWill) - if !ok { - t.Error("Failed to receive Empty Will message") - } -} - -func TestWillSubscribePublishBinaryWill(t *testing.T) { -- iniStr := ` +- configStr := ` - [gateway] -- name = binary -- [broker "local/1"] -- host = localhost +- name = "binary" +- [[broker."local/1"]] +- host = "localhost" - port = 1883 -- will_message = \x01\x02 -- [device "dora/dummy"] -- broker = local +- will_message = "\\x01\\x02" +- [device."dora"] +- type = "dummy" +- broker = "local" - qos = 0 - interval = 10 -- payload = Hello will just publish world. -- type = EnOcean +- payload = "Hello will just publish world." +-` +- expectedWill := true +- ok := genericWillTestDriver(t, configStr, "/binary/will", []byte{1, 2}, expectedWill) +- if !ok { +- t.Error("Failed to receive Empty Will message") +- } +-} +- +-func TestWillSubscribePublishWillWithWillTopic(t *testing.T) { +- configStr := ` +- [gateway] +- name = "with" +- [[broker."local/1"]] +- host = "localhost" +- port = 1883 +- will_message = "msg" +- will_topic = "willtopic" -` -- ok := genericWillTestDriver(t, iniStr, "/binary/will", []byte{1, 2}) +- expectedWill := true +- ok := genericWillTestDriver(t, configStr, "/willtopic", []byte("msg"), expectedWill) - if !ok { - t.Error("Failed to receive Empty Will message") - } -} - +-func TestWillSubscribePublishWillWithNestedWillTopic(t *testing.T) { +- configStr := ` +- [gateway] +- name = "withnested" +- [[broker."local/1"]] +- host = "localhost" +- port = 1883 +- will_message = "msg" +- will_topic = "willtopic/nested" +-` +- expectedWill := true +- ok := genericWillTestDriver(t, configStr, "/willtopic/nested", []byte("msg"), expectedWill) +- if !ok { +- t.Error("Failed to receive nested willtopic Will message") +- } +-} +- -// genericWillTestDriver -// 1. read config string -// 2. connect subscriber and publisher to localhost broker with will message @@ -973,48 +1600,85 @@ -// 4. force disconnect -// 5. check subscriber receives will message - --func genericWillTestDriver(t *testing.T, iniStr string, expectedTopic string, expectedPayload []byte) (ok bool) { +-func genericWillTestDriver(t *testing.T, configStr string, expectedTopic string, expectedPayload []byte, expectedWill bool) (ok bool) { - assert := assert.New(t) - -- conf, err := inidef.LoadConfigByte([]byte(iniStr)) +- conf, err := config.LoadConfigByte([]byte(configStr)) - assert.Nil(err) -- commandChannel := make(chan string) -- go fuji.StartByFileWithChannel(conf, commandChannel) - +- // write config string to temporal file +- f, err := os.Create(tmpTomlName) +- if err != nil { +- t.Error(err) +- } +- _, err = f.WriteString(configStr) +- if err != nil { +- t.Error(err) +- } +- f.Sync() +- +- // execute fuji as external process +- fujiPath, err := filepath.Abs("../fuji") +- if err != nil { +- t.Error("file path not found") +- } +- cmd := exec.Command(fujiPath, "-c", tmpTomlName) +- err = cmd.Start() +- if err != nil { +- t.Error(err) +- } +- +- // subscriber setup - gw, err := gateway.NewGateway(conf) - assert.Nil(err) - - brokers, err := broker.NewBrokers(conf, gw.BrokerChan) - assert.Nil(err) - -- go func() { -- time.Sleep(1 * time.Second) +- subscriberChannel, err := setupWillSubscriber(gw, brokers[0], t) +- if err != config.Error("") { +- t.Error(err) +- } - -- subscriberChannel, err := setupWillSubscriber(gw, brokers[0]) -- if err != inidef.Error("") { -- t.Error(err) -- } +- fin := make(chan bool) - -- time.Sleep(1 * time.Second) +- go func() { +- // check will message +- willCame := true +- select { +- case willMsg := <-subscriberChannel: +- if expectedWill { +- assert.Equal(expectedTopic, willMsg.Topic()) +- assert.Equal(expectedPayload, willMsg.Payload()) +- assert.Equal(byte(0), willMsg.Qos()) +- } else { +- assert.Equal("NO will message received within 1 sec", "unexpected will message received.") +- } +- case <-time.After(time.Second * 2): +- if expectedWill { +- assert.Equal("will message received within 1 sec", "not completed") +- } +- willCame = false +- } +- fin <- willCame +- }() - -- // kill publisher -- brokers[0].FourceClose() -- fmt.Println("broker killed for getting will message") +- // wait for startup of external command process +- time.Sleep(time.Second * 1) - -- // check will message -- willMsg := <-subscriberChannel +- // kill publisher +- err = cmd.Process.Kill() +- if err != nil { +- t.Error(err) +- } +- t.Log("broker killed for getting will message") - -- assert.Equal(expectedTopic, willMsg.Topic()) -- assert.Equal(expectedPayload, willMsg.Payload()) -- assert.Equal(byte(0), willMsg.Qos()) -- }() -- time.Sleep(3 * time.Second) -- ok = true +- ok = <-fin - return ok -} - -// setupWillSubscriber start subscriber process and returnes a channel witch can receive will message. --func setupWillSubscriber(gw *gateway.Gateway, broker *broker.Broker) (chan MQTT.Message, inidef.Error) { +-func setupWillSubscriber(gw *gateway.Gateway, broker *broker.Broker, t *testing.T) (chan MQTT.Message, config.Error) { - // Setup MQTT pub/sub client to confirm published content. - // - messageOutputChannel := make(chan MQTT.Message) @@ -1027,21 +1691,21 @@ - opts.SetDefaultPublishHandler(func(client *MQTT.Client, msg MQTT.Message) { - messageOutputChannel <- msg - }) +- willQoS := 0 +- willTopic := broker.WillTopic +- t.Logf("expected will_topic: %s", willTopic) - - client := MQTT.NewClient(opts) - if client == nil { -- return nil, inidef.Error("NewClient failed") +- return nil, config.Error("NewClient failed") - } - if token := client.Connect(); token.Wait() && token.Error() != nil { -- return nil, inidef.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) +- return nil, config.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) - } - -- qos := 0 -- // assume topicPrefix == "" -- willTopic := fmt.Sprintf("/%s/will", gw.Name) -- client.Subscribe(willTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { +- client.Subscribe(willTopic, byte(willQoS), func(client *MQTT.Client, msg MQTT.Message) { - messageOutputChannel <- msg - }) - -- return messageOutputChannel, inidef.Error("") +- return messageOutputChannel, config.Error("") -} diff -Nru fuji-0.3.0/debian/patches/series fuji-1.0.2/debian/patches/series --- fuji-0.3.0/debian/patches/series 2016-02-26 15:17:05.000000000 +0000 +++ fuji-1.0.2/debian/patches/series 2016-07-15 04:06:42.000000000 +0000 @@ -1 +1,3 @@ remove_test +fix_path_of_paho +fix_function_name diff -Nru fuji-0.3.0/debian/rules fuji-1.0.2/debian/rules --- fuji-0.3.0/debian/rules 2016-02-26 15:17:05.000000000 +0000 +++ fuji-1.0.2/debian/rules 2016-07-15 04:06:42.000000000 +0000 @@ -15,6 +15,6 @@ mv debian/tmp/usr/bin debian/tmp/usr/sbin mkdir -p debian/tmp/etc/fuji-gw - cp config.ini.example debian/tmp/etc/fuji-gw/config.ini + cp config.toml.example debian/tmp/etc/fuji-gw/config.toml override_dh_auto_test: diff -Nru fuji-0.3.0/device/deviceChannel.go fuji-1.0.2/device/deviceChannel.go --- fuji-0.3.0/device/deviceChannel.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/deviceChannel.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff -Nru fuji-0.3.0/device/device.go fuji-1.0.2/device/device.go --- fuji-0.3.0/device/device.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/device.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ log "github.com/Sirupsen/logrus" "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/message" ) @@ -29,8 +29,8 @@ AddSubscribe() error } -// NewDevices is a factory method to create various kind of devices from ini.File -func NewDevices(conf inidef.Config, brokers []*broker.Broker) ([]Devicer, []DeviceChannel, error) { +// NewDevices is a factory method to create various kind of devices from config.Config +func NewDevices(conf config.Config, brokers []*broker.Broker) ([]Devicer, []DeviceChannel, error) { var ret []Devicer var devChannels []DeviceChannel @@ -45,7 +45,7 @@ devChan := NewDeviceChannel() devChannels = append(devChannels, devChan) - switch section.Arg { + switch section.Values["type"] { case "dummy": device, err = NewDummyDevice(section, brokers, devChan) if err != nil { diff -Nru fuji-0.3.0/device/dummy.go fuji-1.0.2/device/dummy.go --- fuji-0.3.0/device/dummy.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/dummy.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,24 +24,24 @@ validator "gopkg.in/validator.v2" "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/message" "github.com/shiguredo/fuji/utils" ) // DummyDevice is an dummy device which outputs only specified payload. type DummyDevice struct { - Name string `validate:"max=256,regexp=[^/]+,validtopic"` - Broker []*broker.Broker - BrokerName string - QoS byte `validate:"min=0,max=2"` - InputPort InputPortType - Interval int `validate:"min=1"` - Payload []byte `validate:"max=4096"` - Type string `validate:"max=256"` - Retain bool - Subscribe bool - DeviceChan DeviceChannel // GW -> device + Name string `validate:"max=256,regexp=[^/]+,validtopic"` + Broker []*broker.Broker + BrokerName string + QoS byte `validate:"min=0,max=2"` + InputPort InputPortType + Interval int `validate:"min=1"` + Payload []byte `validate:"max=4096"` + Type string `validate:"max=256"` + Retain bool + SubscribeTopic message.TopicString // initialized as "" + DeviceChan DeviceChannel // GW -> device } // String retruns dummy device information @@ -50,7 +50,7 @@ } // NewDummyDevice creates dummy device which outputs specified string/binary payload. -func NewDummyDevice(section inidef.ConfigSection, brokers []*broker.Broker, devChan DeviceChannel) (DummyDevice, error) { +func NewDummyDevice(section config.ConfigSection, brokers []*broker.Broker, devChan DeviceChannel) (DummyDevice, error) { ret := DummyDevice{ Name: section.Name, DeviceChan: devChan, @@ -95,7 +95,9 @@ sub, ok := values["subscribe"] if ok && sub == "true" { - ret.Subscribe = true + ret.SubscribeTopic = message.TopicString{ + Str: strings.Join([]string{ret.Name, ret.Type, "subscribe"}, "/"), + } } // Validation @@ -107,7 +109,7 @@ func (device *DummyDevice) Validate() error { validator := validator.NewValidator() - validator.SetValidationFunc("validtopic", inidef.ValidMqttPublishTopic) + validator.SetValidationFunc("validtopic", config.ValidMqttPublishTopic) if err := validator.Validate(device); err != nil { return err } @@ -139,7 +141,7 @@ } channel <- msg case msg, _ := <-device.DeviceChan.Chan: - if !strings.HasSuffix(msg.Topic, device.Name) { + if device.SubscribeTopic.Str == "" || !strings.HasSuffix(msg.Topic, device.SubscribeTopic.Str) { continue } @@ -160,11 +162,11 @@ } func (device DummyDevice) AddSubscribe() error { - if !device.Subscribe { + if device.SubscribeTopic.Str == "" { return nil } for _, b := range device.Broker { - b.AddSubscribed(device.Name, device.QoS) + b.AddSubscribed(device.SubscribeTopic, device.QoS) } return nil } diff -Nru fuji-0.3.0/device/dummy_test.go fuji-1.0.2/device/dummy_test.go --- fuji-0.3.0/device/dummy_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/dummy_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,24 +20,25 @@ "github.com/stretchr/testify/assert" "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" ) func TestNewDummyDevice(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/dummy"] - broker = sango + configStr := ` +[device."dora/dummy"] + broker = "sango" qos = 1 dummy = true interval = 10 - payload = Hello world. + payload = "Hello world." ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - b, err := NewDummyDevice(conf.Sections[1], brokers, NewDeviceChannel()) + b, err := NewDummyDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.Nil(err) assert.NotNil(b.Broker) assert.Equal("dora", b.Name) @@ -49,47 +50,50 @@ func TestNewDummyDeviceInvalidInterval(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/dummy"] - broker = sango + configStr := ` +[device."dora/dummy"] + broker = "sango" interval = -1 qos = 1 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - _, err = NewDummyDevice(conf.Sections[1], brokers, NewDeviceChannel()) + _, err = NewDummyDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.NotNil(err) } func TestNewDummyDeviceInvalidQoS(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/dummy"] - broker = sango + configStr := ` +[device."dora/dummy"] + broker = "sango" interval = -1 qos = -1 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - _, err = NewDummyDevice(conf.Sections[1], brokers, NewDeviceChannel()) + _, err = NewDummyDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.NotNil(err) } func TestNewDummyDeviceInvalidBroker(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/dummy"] - broker = doesNotExist + configStr := ` +[device."dora/dummy"] + broker = "doesNotExist" interval = 10 qos = 1 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - _, err = NewDummyDevice(conf.Sections[1], brokers, NewDeviceChannel()) + _, err = NewDummyDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.NotNil(err) } diff -Nru fuji-0.3.0/device/porttype.go fuji-1.0.2/device/porttype.go --- fuji-0.3.0/device/porttype.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/porttype.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff -Nru fuji-0.3.0/device/serial.go fuji-1.0.2/device/serial.go --- fuji-0.3.0/device/serial.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/serial.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,24 +26,24 @@ validator "gopkg.in/validator.v2" "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/message" ) type SerialDevice struct { - Name string `validate:"max=256,regexp=[^/]+,validtopic"` - Broker []*broker.Broker - BrokerName string - QoS byte `validate:"min=0,max=2"` - InputPort InputPortType - Serial string `validate:"max=256"` - Baud int `validate:"min=0"` - Size int `validate:"min=0,max=256"` - Type string `validate:"max=256"` - Interval int `validate:"min=0"` - Retain bool - Subscribe bool - DeviceChan DeviceChannel // GW -> device + Name string `validate:"max=256,regexp=[^/]+,validtopic"` + Broker []*broker.Broker + BrokerName string + QoS byte `validate:"min=0,max=2"` + InputPort InputPortType + Serial string `validate:"max=256"` + Baud int `validate:"min=0"` + Size int `validate:"min=0,max=256"` + Type string `validate:"max=256"` + Interval int `validate:"min=0"` + Retain bool + SubscribeTopic message.TopicString // initialized as "" + DeviceChan DeviceChannel // GW -> device } func (device SerialDevice) String() string { @@ -54,9 +54,9 @@ return fmt.Sprintf("%#v", device) } -// NewSerialDevice read inidef.ConfigSection and returnes SerialDevice. +// NewSerialDevice read config.ConfigSection and returnes SerialDevice. // If config validation failed, return error -func NewSerialDevice(section inidef.ConfigSection, brokers []*broker.Broker, devChan DeviceChannel) (SerialDevice, error) { +func NewSerialDevice(section config.ConfigSection, brokers []*broker.Broker, devChan DeviceChannel) (SerialDevice, error) { ret := SerialDevice{ Name: section.Name, DeviceChan: devChan, @@ -85,7 +85,7 @@ ret.QoS = byte(qos) } // TODO: check it is true or not - // ret.InputPort = InputPortType(inidef.INPUT_PORT_SERIAL) + // ret.InputPort = InputPortType(INPUT_PORT_SERIAL) ret.InputPort = InputPortType(INPUT_PORT_DUMMY) ret.Serial = values["serial"] baud, err := strconv.Atoi(values["baud"]) @@ -112,7 +112,9 @@ sub, ok := values["subscribe"] if ok && sub == "true" { - ret.Subscribe = true + ret.SubscribeTopic = message.TopicString{ + Str: strings.Join([]string{ret.Name, ret.Type, "subscribe"}, "/"), + } } if err := ret.Validate(); err != nil { @@ -124,7 +126,7 @@ func (device *SerialDevice) Validate() error { validator := validator.NewValidator() - validator.SetValidationFunc("validtopic", inidef.ValidMqttPublishTopic) + validator.SetValidationFunc("validtopic", config.ValidMqttPublishTopic) if err := validator.Validate(device); err != nil { return err } @@ -238,7 +240,7 @@ channel <- msg case msg, _ := <-device.DeviceChan.Chan: log.Infof("msg topic:, %v / %v", msg.Topic, device.Name) - if !strings.HasSuffix(msg.Topic, device.Name) { + if device.SubscribeTopic.Str == "" || !strings.HasSuffix(msg.Topic, device.SubscribeTopic.Str) { continue } log.Infof("msg reached to device, %v", msg) @@ -265,11 +267,11 @@ } func (device SerialDevice) AddSubscribe() error { - if !device.Subscribe { + if device.SubscribeTopic.Str == "" { return nil } for _, b := range device.Broker { - b.AddSubscribed(device.Name, device.QoS) + b.AddSubscribed(device.SubscribeTopic, device.QoS) } return nil } diff -Nru fuji-0.3.0/device/serial_test.go fuji-1.0.2/device/serial_test.go --- fuji-0.3.0/device/serial_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/serial_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,114 +20,118 @@ "github.com/stretchr/testify/assert" "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" ) func TestNewSerialDevice(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/serial"] - broker = sango + configStr := ` +[device."dora"] + type = "serial" + broker = "sango" qos = 1 - serial = /dev/tty.ble + serial = "/dev/tty.ble" baud = 9600 size = 4 - type = BLE ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - b, err := NewSerialDevice(conf.Sections[1], brokers, NewDeviceChannel()) + b, err := NewSerialDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.Nil(err) assert.NotNil(b.Broker) assert.Equal("dora", b.Name) assert.Equal(byte(1), b.QoS) assert.Equal(4, b.Size) - assert.Equal("BLE", b.Type) + assert.Equal("serial", b.Type) } func TestNewSerialDeviceNotSetSize(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/serial"] - broker = sango + configStr := ` +[device."dora"] + type = "serial" + broker = "sango" qos = 1 - serial = /dev/tty.ble + serial = "/dev/tty.ble" baud = 9600 - type = BLE ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - b, err := NewSerialDevice(conf.Sections[1], brokers, NewDeviceChannel()) + b, err := NewSerialDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.Nil(err) assert.NotNil(b.Broker) assert.Equal("dora", b.Name) assert.Equal(0, b.Size) - assert.Equal("BLE", b.Type) + assert.Equal("serial", b.Type) } func TestNewSerialDeviceInvalidInterval(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/serial"] - broker = sango + configStr := ` +[device."dora"] + type = "serial" + broker = "sango" interval = -1 qos = 1 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - _, err = NewSerialDevice(conf.Sections[1], brokers, NewDeviceChannel()) + _, err = NewSerialDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.NotNil(err) } func TestNewSerialDeviceInvalidQoS(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/serial"] - broker = sango + configStr := ` +[device."dora"] + type = "serial" + broker = "sango" qos = -1 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - _, err = NewSerialDevice(conf.Sections[1], brokers, NewDeviceChannel()) + _, err = NewSerialDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.NotNil(err) } func TestNewSerialDeviceInvalidBroker(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/serial"] - broker = doesNotExist + configStr := ` +[device."dora"] + type = "serial" + broker = "doesNotExist" qos = 1 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - _, err = NewSerialDevice(conf.Sections[1], brokers, NewDeviceChannel()) + _, err = NewSerialDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.NotNil(err) } func TestNewSerialDeviceInvalidBaud(t *testing.T) { assert := assert.New(t) - iniStr := ` -[device "dora/serial"] - broker = sango + configStr := ` +[device."dora"] + type = "serial" + broker = "sango" qos = -1 baud = -9600 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) b1 := &broker.Broker{Name: "sango"} brokers := []*broker.Broker{b1} - _, err = NewSerialDevice(conf.Sections[1], brokers, NewDeviceChannel()) + _, err = NewSerialDevice(conf.Sections[0], brokers, NewDeviceChannel()) assert.NotNil(err) } diff -Nru fuji-0.3.0/device/status.go fuji-1.0.2/device/status.go --- fuji-0.3.0/device/status.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/status.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,9 @@ package device import ( + "encoding/json" "fmt" + "net" "strconv" "strings" "time" @@ -25,7 +27,7 @@ "github.com/shirou/gopsutil/mem" validator "gopkg.in/validator.v2" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/message" ) @@ -39,6 +41,15 @@ BrokerName string VirtualMemory []string } +type InterfaceAddress struct { + Name string + Addr []string +} +type IpAddressStatus struct { + GatewayName string + BrokerName string + Interfaces []string +} type Status struct { Name string `validate:"max=256,regexp=[^/]+,validtopic"` GatewayName string @@ -46,6 +57,7 @@ Interval int CPU CPUStatus Memory MemoryStatus + IpAddress IpAddressStatus } func (device Status) String() string { @@ -142,8 +154,76 @@ return ret } -// NewStatus returnes status from ini File, not ini.Section. -func NewStatus(conf inidef.Config) (Devicer, error) { +func (i IpAddressStatus) Get() []message.Message { + ret := []message.Message{} + + ifs, err := net.Interfaces() + if err != nil { + log.Warnf("ip_address get err, %v", err) + return nil + } + for _, name := range i.Interfaces { + msg := message.Message{ + Sender: "status", + Type: "status", + BrokerName: i.BrokerName, + } + body := []byte{} + if name == "all" { + addressList := []InterfaceAddress{} + for _, intf := range ifs { + addrs, err := intf.Addrs() + if err != nil { + log.Errorf("interface Addrs error %s", err) + continue + } + addrStrList := []string{} + for _, a := range addrs { + addrStrList = append(addrStrList, a.String()) + } + addressList = append(addressList, InterfaceAddress{ + Name: intf.Name, + Addr: addrStrList}) + } + body, err = json.Marshal(addressList) + if err != nil { + log.Errorf("json encode error %s", err) + } + } else { + addrStrList := []string{} + for _, intf := range ifs { + if name != intf.Name { + continue + } + addrs, err := intf.Addrs() + if err != nil { + log.Errorf("interface Addrs error %s", err) + continue + } + for _, a := range addrs { + addrStrList = append(addrStrList, a.String()) + } + break + } + body, err = json.Marshal(addrStrList) + if err != nil { + log.Errorf("json encode error %s", err) + } + } + msg.Body = []byte(body) + + topic, err := genTopic(i.GatewayName, "ip_address", "interface", name) + if err != nil { + log.Errorf("invalid topic, %s/%s/%s/%s", i.GatewayName, "ip_address", "interface", "all") + } + msg.Topic = topic + ret = append(ret, msg) + } + return ret +} + +// NewStatus returnes status from config file, not config.Sections. +func NewStatus(conf config.Config) (Devicer, error) { ret := Status{ Name: "status", GatewayName: conf.GatewayName, @@ -154,6 +234,7 @@ if section.Type != "status" { continue } + if section.Name != "" { // skip if status child group continue } @@ -207,6 +288,17 @@ mem.VirtualMemory = virtual_memory } ret.Memory = mem + + case "ip_address": + interfaces := parseStatus(section.Values["interface"]) + ip_address := IpAddressStatus{ + GatewayName: conf.GatewayName, + BrokerName: ret.BrokerName, + } + if len(interfaces) > 0 { + ip_address.Interfaces = interfaces + } + ret.IpAddress = ip_address default: log.Errorf("unknown status type: %v", section.Name) continue @@ -227,7 +319,7 @@ func (device *Status) Validate() error { validator := validator.NewValidator() - validator.SetValidationFunc("validtopic", inidef.ValidMqttPublishTopic) + validator.SetValidationFunc("validtopic", config.ValidMqttPublishTopic) if err := validator.Validate(device); err != nil { return err } @@ -242,6 +334,7 @@ msgs = append(msgs, device.CPU.Get()...) msgs = append(msgs, device.Memory.Get()...) + msgs = append(msgs, device.IpAddress.Get()...) if len(msgs) > 0 { for _, msg := range msgs { channel <- msg diff -Nru fuji-0.3.0/device/status_test.go fuji-1.0.2/device/status_test.go --- fuji-0.3.0/device/status_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/device/status_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ "github.com/stretchr/testify/assert" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" ) func TestParseStatus(t *testing.T) { @@ -36,22 +36,25 @@ r = parseStatus("") assert.Equal([]string{}, r) } + func TestStatus(t *testing.T) { assert := assert.New(t) - iniStr := ` -[broker "sango"] - host = 192.168.1.20 + configStr := ` +[[broker."sango"]] + host = "192.168.1.20" port = 1033 -[status "cpu"] - cpu_times = user, system, idle, nice, iowait, irq, softirq, guest -[status "memory"] - virtual_memory = total, available, percent, used, free +[[status."cpu"]] + cpu_times = "user, system, idle, nice, iowait, irq, softirq, guest" +[[status."memory"]] + virtual_memory = "total, available, percent, used, free" +[[status."ip_address"]] + interface = "eth0, lo0" [status] - broker = sango + broker = "sango" interval = 10 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) assert.Nil(err) tt, err := NewStatus(conf) assert.Nil(err) @@ -63,6 +66,63 @@ assert.Equal(8, len(st.CPU.CpuTimes)) assert.Equal(5, len(st.Memory.VirtualMemory)) + assert.Equal(2, len(st.IpAddress.Interfaces)) +} + +func TestNewStatusInvalidConfig(t *testing.T) { + assert := assert.New(t) + + { // status is not found + configStr := ` +[[broker."sango"]] + host = "192.168.1.20" + port = 1033 +` + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + _, err = NewStatus(conf) + assert.NotNil(err) + } + { // broker is not found + configStr := ` +[[broker."sango"]] + host = "192.168.1.20" + port = 1033 +[status] + interval = 10 +` + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + _, err = NewStatus(conf) + assert.NotNil(err) + } + { // broker is empty + configStr := ` +[[broker."sango"]] + host = "192.168.1.20" + port = 1033 +[status] + broker = "" + interval = 10 +` + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + _, err = NewStatus(conf) + assert.NotNil(err) + } + { // interval is empty + configStr := ` +[[broker."sango"]] + host = "192.168.1.20" + port = 1033 +[status] + broker = "sango" +` + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + _, err = NewStatus(conf) + assert.NotNil(err) + } } func TestCPUGet(t *testing.T) { @@ -82,3 +142,25 @@ msgs := c.Get() assert.Equal(4, len(msgs)) } + +func TestIpAddressAllGet(t *testing.T) { + assert := assert.New(t) + + i := IpAddressStatus{ + Interfaces: []string{"all"}, + } + assert.NotNil(i) + msgs := i.Get() + assert.True(len(msgs) > 0) +} + +func TestIpAddressLoGet(t *testing.T) { + assert := assert.New(t) + + i := IpAddressStatus{ + Interfaces: []string{"lo0", "en0"}, + } + assert.NotNil(i) + msgs := i.Get() + assert.True(len(msgs) > 0) +} diff -Nru fuji-0.3.0/gateway/gateway.go fuji-1.0.2/gateway/gateway.go --- fuji-0.3.0/gateway/gateway.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/gateway/gateway.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,8 +27,8 @@ validator "gopkg.in/validator.v2" "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/device" - "github.com/shiguredo/fuji/inidef" "github.com/shiguredo/fuji/message" ) @@ -55,7 +55,7 @@ ) func init() { - validator.SetValidationFunc("validtopic", inidef.ValidMqttPublishTopic) + validator.SetValidationFunc("validtopic", config.ValidMqttPublishTopic) } func (gateway Gateway) String() string { @@ -63,8 +63,8 @@ } // NewGateway returns Gateway instance with config object -func NewGateway(conf inidef.Config) (*Gateway, error) { - var section inidef.ConfigSection +func NewGateway(conf config.Config) (*Gateway, error) { + var section config.ConfigSection for _, s := range conf.Sections { if s.Type == "gateway" { section = s diff -Nru fuji-0.3.0/gateway/gateway_test.go fuji-1.0.2/gateway/gateway_test.go --- fuji-0.3.0/gateway/gateway_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/gateway/gateway_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,13 +20,13 @@ "github.com/stretchr/testify/assert" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" ) func TestNewGateway(t *testing.T) { assert := assert.New(t) - conf, err := inidef.LoadConfig("../tests/testing_conf.ini") + conf, err := config.LoadConfig("../tests/testing_conf.toml") gw, err := NewGateway(conf) assert.Nil(err) assert.Equal("ham", gw.Name) @@ -39,83 +39,91 @@ assert := assert.New(t) { // includes plus - iniStr := ` + configStr := ` [gateway] -name = bone+lessham +name = "bone+lessham" ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } { // includes sharp - iniStr := ` + configStr := ` [gateway] -name = ` + "`" + `bone\#lessham` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) +name = "bone#lessham"` + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } { // too long - iniStr := ` + configStr := ` [gateway] -name = bonelesshaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +name = "bonelesshaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } { // \\U0000 string - iniStr := fmt.Sprintf(` + configStr := fmt.Sprintf(` [gateway] -name = na%cme +name = "na%cme" `, '\u0000') - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } + { // empty + configStr := ` +[gateway] +name = "" +` + _, err := config.LoadConfigByte([]byte(configStr)) + assert.NotNil(err) + } } func TestNewGatewayMaxRetryCount(t *testing.T) { assert := assert.New(t) { // default - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) gw, err := NewGateway(conf) assert.Nil(err) assert.Equal(3, gw.MaxRetryCount) } { // specified - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" max_retry_count = 10 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) gw, err := NewGateway(conf) assert.Nil(err) assert.Equal(10, gw.MaxRetryCount) } { // minus fail validation - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" max_retry_count = -10 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } { // invalid int - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" max_retry_count = aabbcc ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } @@ -125,43 +133,43 @@ assert := assert.New(t) { // default - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) gw, err := NewGateway(conf) assert.Nil(err) assert.Equal(3, gw.RetryInterval) } { // specified - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" retry_interval = 10 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) gw, err := NewGateway(conf) assert.Nil(err) assert.Equal(10, gw.RetryInterval) } { // minus fail validation - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" retry_interval = -10 ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } { // invalid int - iniStr := ` + configStr := ` [gateway] -name = sango +name = "sango" retry_interval = aabbcc ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) _, err = NewGateway(conf) assert.NotNil(err) } diff -Nru fuji-0.3.0/.gitignore fuji-1.0.2/.gitignore --- fuji-0.3.0/.gitignore 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/.gitignore 2016-03-23 04:35:15.000000000 +0000 @@ -3,5 +3,4 @@ opkg-utils packages/opkg_files/control packages/opkg_files/control.tar.gz -Godeps/_workspace/ -Godeps/Readme +vendor diff -Nru fuji-0.3.0/glide.lock fuji-1.0.2/glide.lock --- fuji-0.3.0/glide.lock 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/glide.lock 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,39 @@ +hash: 63597bc89f2278a721ebd93484370043330aa3f178800bd2f0fa6bb89985c23e +updated: 2016-03-06T02:20:06.358889077+09:00 +imports: +- name: github.com/BurntSushi/toml + version: 5c4df71dfe9ac89ef6287afc05e4c1b16ae65a1e +- name: github.com/codegangsta/cli + version: a2943485b110df8842045ae0600047f88a3a56a1 +- name: github.com/eclipse/paho.mqtt.golang + version: 183329365eb3c151b3f8403f90c89cf4e21ed739 + subpackages: + - packets +- name: github.com/go-ole/go-ole + version: 2b4785954496f7121eb0934e9dc55e85ad40ad8f + subpackages: + - oleutil +- name: github.com/shirou/gopsutil + version: e77438504d45b9985c99a75730fe65220ceea00e + subpackages: + - cpu + - cpu + - mem + - internal/common +- name: github.com/Sirupsen/logrus + version: be52937128b38f1d99787bb476c789e2af1147f1 +- name: github.com/StackExchange/wmi + version: f3e2bae1e0cb5aef83e319133eabfee30013a4a5 +- name: github.com/tarm/serial + version: a53c419ae7ba5705d100024728f5254b81dd73e9 +- name: golang.org/x/net + version: 7f88271ea9913b72aca44fa7fc8af919eacc17ce + subpackages: + - websocket +- name: golang.org/x/sys + version: 50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e + subpackages: + - unix +- name: gopkg.in/validator.v2 + version: 3e4f037f12a1221a0864cf0dd2e81c452ab22448 +devImports: [] diff -Nru fuji-0.3.0/glide.yaml fuji-1.0.2/glide.yaml --- fuji-0.3.0/glide.yaml 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/glide.yaml 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,29 @@ +package: github.com/shiguredo/fuji +import: +- package: github.com/BurntSushi/toml + version: 5c4df71dfe9ac89ef6287afc05e4c1b16ae65a1e +- package: github.com/Sirupsen/logrus + version: be52937128b38f1d99787bb476c789e2af1147f1 +- package: github.com/eclipse/paho.mqtt.golang + version: 183329365eb3c151b3f8403f90c89cf4e21ed739 +- package: github.com/go-ole/go-ole + version: 2b4785954496f7121eb0934e9dc55e85ad40ad8f +- package: github.com/shirou/gopsutil + version: e77438504d45b9985c99a75730fe65220ceea00e + subpackages: + - cpu + - cpu + - mem +- package: github.com/tarm/serial + version: a53c419ae7ba5705d100024728f5254b81dd73e9 +- package: golang.org/x/net + version: 7f88271ea9913b72aca44fa7fc8af919eacc17ce + subpackages: + - websocket +- package: golang.org/x/sys + version: 50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e + subpackages: + - unix +- package: gopkg.in/validator.v2 + version: 3e4f037f12a1221a0864cf0dd2e81c452ab22448 +- package: github.com/codegangsta/cli diff -Nru fuji-0.3.0/Godeps/Godeps.json fuji-1.0.2/Godeps/Godeps.json --- fuji-0.3.0/Godeps/Godeps.json 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/Godeps/Godeps.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -{ - "ImportPath": "github.com/shiguredo/fuji", - "GoVersion": "go1.5.1", - "Deps": [ - { - "ImportPath": "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git", - "Comment": "v0.9.1-14-g546c47a", - "Rev": "546c47a6d0e9492e77f6f37473d59c36a708e08b" - }, - { - "ImportPath": "github.com/Sirupsen/logrus", - "Comment": "v0.7.1", - "Rev": "3fc34d061b9c78a70db853c7cb6b0576b6d4f32d" - }, - { - "ImportPath": "github.com/codegangsta/cli", - "Comment": "1.2.0-95-g9b2bd2b", - "Rev": "9b2bd2b3489748d4d0a204fa4eb2ee9e89e0ebc6" - }, - { - "ImportPath": "github.com/go-ini/ini", - "Comment": "v0-16-g1772191", - "Rev": "177219109c97e7920c933e21c9b25f874357b237" - }, - { - "ImportPath": "github.com/pborman/uuid", - "Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4" - }, - { - "ImportPath": "github.com/shirou/gopsutil/common", - "Comment": "1.0.0-160-g82a76c0", - "Rev": "82a76c01e3af444ce144b30f228467976ef75864" - }, - { - "ImportPath": "github.com/shirou/gopsutil/cpu", - "Comment": "1.0.0-160-g82a76c0", - "Rev": "82a76c01e3af444ce144b30f228467976ef75864" - }, - { - "ImportPath": "github.com/shirou/gopsutil/mem", - "Comment": "1.0.0-160-g82a76c0", - "Rev": "82a76c01e3af444ce144b30f228467976ef75864" - }, - { - "ImportPath": "github.com/tarm/serial", - "Rev": "e3f4c97bb7137112ddfc06cc44a939e45f41d941" - }, - { - "ImportPath": "golang.org/x/net/websocket", - "Rev": "db8e4de5b2d6653f66aea53094624468caad15d2" - }, - { - "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "59fc8e570cd707a33a93842b00a9aae4b5cd38b2" - }, - { - "ImportPath": "gopkg.in/validator.v2", - "Rev": "8e445b9dc14ab1a1a78cc1f712df991307173ee6" - } - ] -} diff -Nru fuji-0.3.0/inidef/ini.go fuji-1.0.2/inidef/ini.go --- fuji-0.3.0/inidef/ini.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/inidef/ini.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,187 +0,0 @@ -// Copyright 2015 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package inidef - -import ( - "errors" - "fmt" - "io/ioutil" - "reflect" - "regexp" - "strings" - "unicode/utf8" - - log "github.com/Sirupsen/logrus" - "github.com/go-ini/ini" -) - -var ( - ReU0 *regexp.Regexp - ReWild *regexp.Regexp -) - -type AnyError interface{} - -type Error string - -func (e Error) Error() string { - return string(e) -} - -// NilOrString defines the value is nil or empty -type NilOrString interface{} - -// init is automatically invoked at initial time. -func init() { - ReU0 = regexp.MustCompile("\u0000") - ReWild = regexp.MustCompile("[+#]+") -} - -func IsNil(str NilOrString) bool { - if str == nil { - return true - } - return false -} -func String(str NilOrString) string { - stringValue, ok := str.(string) - if ok == false { - return ("nil") - } - return stringValue -} - -// ValidMqttPublishTopic validates the Topic is validate or not -// This is used with validator packages. -func ValidMqttPublishTopic(v interface{}, param string) error { - str := reflect.ValueOf(v) - if str.Kind() != reflect.String { - return errors.New("ValidMqttPublishTopic only validates strings") - } - if !utf8.ValidString(str.String()) { - return errors.New("not a valid UTF8 string") - } - - if ReU0.FindString(str.String()) != "" { - return errors.New("Topic SHALL NOT include \\U0000 character") - } - - if ReWild.FindString(str.String()) != "" { - return errors.New("SHALL NOT MQTT pub-topic include wildard character") - } - return nil -} - -type Config struct { - GatewayName string - BrokerNames []string - - Sections []ConfigSection -} - -type ConfigSection struct { - Title string - Type string - Name string - Arg string - - Values map[string]string -} - -// Loadini loads ini format file from confPath arg and returns []ConfigSection. -// ConfigSection has a Type, Name and arg. -// example: -// [broker "sango"] -// [broker "sango/1"] -// [broker "sango/2"] -// -// ret = [ -// ConfigSection{Type: "broker", Name: "sango"}, -// ConfigSection{Type: "broker", Name: "sango", Arg: "1"}, -// ConfigSection{Type: "broker", Name: "sango", Arg: "2"}, -// ] -func LoadConfig(confPath string) (Config, error) { - dat, err := ioutil.ReadFile(confPath) - if err != nil { - return Config{}, err - } - - return LoadConfigByte(dat) -} - -// LoadConfigByte returnes []ConfigSection from []byte. -// This is invoked from LoadConfig. -func LoadConfigByte(conf []byte) (Config, error) { - cfg, err := ini.Load(conf) - - config := Config{} - - var sections []ConfigSection - var bn []string - - for _, section := range cfg.Sections() { - key := section.Name() - - k := strings.Fields(key) - if len(k) > 2 { - log.Errorf("invalid section(space), %v", k) - continue - } - rt := ConfigSection{ - Title: key, - Type: k[0], - Values: section.KeysHash(), - } - if rt.Type == "gateway" { - name, ok := rt.Values["name"] - if !ok { - return config, fmt.Errorf("gateway has not name") - } - config.GatewayName = name - } - - // type only - if len(k) == 1 { - sections = append(sections, rt) - continue - } - - // parse name and args - t := strings.TrimFunc(k[1], func(c rune) bool { - if c == '"' { - return true - } - return false - }) - tt := strings.Split(t, "/") - if len(tt) > 2 { - log.Errorf("invalid section(slash), %v", t) - continue - } - rt.Name = tt[0] - if len(tt) == 2 { // if args exists, store it - rt.Arg = tt[1] - } - if rt.Type == "broker" { - bn = append(bn, rt.Name) - } - sections = append(sections, rt) - } - - config.Sections = sections - config.BrokerNames = bn - - return config, err -} diff -Nru fuji-0.3.0/inidef/ini_test.go fuji-1.0.2/inidef/ini_test.go --- fuji-0.3.0/inidef/ini_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/inidef/ini_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -// Copyright 2015 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package inidef - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func Test_LoadConfigByte(t *testing.T) { - assert := assert.New(t) - - iniStr := ` -[status "cpu/1"] - cpu_times = user, system, idle, nice, iowait, irq, softirq, guest -[status "memory"] - virtual_memory = total, available, percent, used, free -[status] - broker = sango - interval = 10 -` - - ret, err := LoadConfigByte([]byte(iniStr)) - assert.Nil(err) - assert.Equal(4, len(ret.Sections)) // DEFAULT is created - s := ret.Sections[1] - assert.Equal("status", s.Type) - assert.Equal("cpu", s.Name) - assert.Equal("1", s.Arg) - - s = ret.Sections[2] - assert.Equal("status", s.Type) - assert.Equal("memory", s.Name) - assert.Equal("", s.Arg) -} diff -Nru fuji-0.3.0/INSTALL.rst fuji-1.0.2/INSTALL.rst --- fuji-0.3.0/INSTALL.rst 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/INSTALL.rst 2016-03-23 04:35:15.000000000 +0000 @@ -2,7 +2,7 @@ MQTT gateway 'Fuji' Install Instruction ####################################### -:version: 0.2.3 +:version: 1.0.2 Install ============ @@ -15,49 +15,49 @@ #. Download tar.gz file #. Extract tar.gz file -#. A executable binary will be placed at ./fuji/fuji-gw. A sample config files is ./fuji/config.ini.example. +#. A executable binary will be placed at ./fuji/fuji-gw. A sample config files is ./fuji/config.toml.example. :: - $ tar xvfz fuji-gw_0.2.3_linux_amd64.tar.gz + $ tar xvfz fuji-gw_1.0.2_linux_amd64.tar.gz For Raspberry Pi (Raspbian) -------------------------------------- -:Package: fuji-gw_0.2.3_raspi_arm6.deb +:Package: fuji-gw_1.0.2_raspi_arm6.deb #. Download a package #. Install by `dpkg -i` -#. A executable binary will be placed at /usr/local/bin/fuji-gw. A sample config file is /etc/fuji-gw/config.ini. +#. A executable binary will be placed at /usr/local/bin/fuji-gw. A sample config file is /etc/fuji-gw/config.toml. #. Auto start file is setup as /etc/init.d/fuji-gw. -#. Once you setup /etc/fuji-gw/config.ini correctly, fuji-gw process automatically starts after reboot. +#. Once you setup /etc/fuji-gw/config.toml correctly, fuji-gw process automatically starts after reboot. Note: The fuji-gw process runs as a root. :: - $ dpkg -i fuji-gw_0.2.3_raspi_arm6.deb + $ dpkg -i fuji-gw_1.0.2_raspi_arm6.deb $ dpkg -i fuji-gw__raspi_arm6.deb For Raspberry Pi 2(Raspbian) ----------------------------- -:Package: fuji-gw_0.2.3_raspi2_arm7.deb +:Package: fuji-gw_1.0.2_raspi2_arm7.deb #. Download a package #. Install by `dpkg -i` -#. A executable binary will be placed at /usr/local/bin/fuji-gw. A sample config file is /etc/fuji-gw/config.ini. +#. A executable binary will be placed at /usr/local/bin/fuji-gw. A sample config file is /etc/fuji-gw/config.toml. :: - $ dpkg -i fuji-gw_0.2.3_raspi2_arm7.deb - $ fuji-gw -c /etc/fuji-gw/config.ini + $ dpkg -i fuji-gw_1.0.2_raspi2_arm7.deb + $ fuji-gw -c /etc/fuji-gw/config.toml For Armadillo-IoT -------------------- -:tar.gz File: fuji-gw_0.2.3_arm5.tar.gz +:tar.gz File: fuji-gw_1.0.2_arm5.tar.gz (Note:) If you want to embed Fuji to startup image, please refer `Armadillo-IoT Gateway Standard manual `_ of Atmark-Techno. @@ -80,17 +80,17 @@ ftp> cd pub ftp> binary ftp> put fuji-gw - ftp> put config.ini.example + ftp> put config.toml.example For Intel Edison ------------------- -:Package: fuji-gw_0.2.3_edison_386.ipk +:Package: fuji-gw_1.0.2_edison_386.ipk #. Login to Intel Edison #. Download package #. Install using `opkg install` command. -#. A executable binary will be placed at ./fuji/fuji-gw. A sample config files is ./fuji/config.ini.example. +#. A executable binary will be placed at ./fuji/fuji-gw. A sample config files is ./fuji/config.toml.example. :: @@ -122,31 +122,31 @@ In this config file, we use dummy device function of Fuji. A dummy device can send some static data to MQTT Broker same as an Sensor. Since all user can use only topic under `/#` on the Sango, set `topic_prefix` value as is. -.. code-block:: ini +.. code-block:: toml [gateway] - name = fuji + name = "fuji" - [broker "sango"] + [[broker."sango"]] - host = + host = "" port = 1883 - username = - password = + username = "" + password = "" retry_interval = 10 - topic_prefix = + topic_prefix = "" - [device "test/dummy"] + [device."test/dummy"] - broker = sango + broker = "sango" qos = 0 interval = 10 - payload = Hello MQTT. + payload = "Hello MQTT." type = Dummy @@ -167,33 +167,33 @@ - password: pass -.. code-block:: ini +.. code-block:: toml [gateway] - name = fuji + name = "fuji" - [broker "sango"] + [[broker."sango"]] - host = sango.example.com + host = "sango.example.com" port = 1883 - username = shiguredo - password = pass + username = "shiguredo" + password = "pass" retry_interval = 10 - topic_prefix = shiguredo@github + topic_prefix = "shiguredo@github" - [device "test/dummy"] + [device."test/dummy"] - broker = sango + broker = "sango" qos = 0 interval = 10 - payload = Hello MQTT. + payload = "Hello MQTT." - type = Dummy + type = "Dummy" diff -Nru fuji-0.3.0/Makefile fuji-1.0.2/Makefile --- fuji-0.3.0/Makefile 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/Makefile 2016-03-23 04:35:15.000000000 +0000 @@ -9,11 +9,12 @@ REPO="github.com/shiguredo/fuji/cmd/fuji" TEST_LIST := tests -TAG=0.3.0 +TAG=1.0.2 REV=`git rev-parse HEAD | cut -c1-7` ARTIFACTS=downloads BUILDDIR=build LDFLAGS=-ldflags "-X main.version=${TAG}-${REV}" +TARGETS_NOVENDOR=$(shell glide novendor) ALL_LIST = $(TEST_LIST) @@ -22,7 +23,7 @@ all: build test raspi raspi2 edison armadillo fmt: - go fmt ./... + @echo $(TARGETS_NOVENDOR) | xargs go fmt doc: fmt # golint ./... @@ -38,43 +39,43 @@ arm5: deps GOARM=5 gox $(LDFLAGS) -os="linux" -arch="arm" -output=$(BUILDDIR)/arm5/fuji/fuji-gw $(REPO) - cp -p packages/config.simple.ini.example $(BUILDDIR)/arm5/fuji/config.ini.example + cp -p packages/config.simple.toml.example $(BUILDDIR)/arm5/fuji/config.toml.example cd $(BUILDDIR)/arm5/ && tar zcvf ../../$(ARTIFACTS)/fuji-gw_$(TAG)_arm5.tar.gz fuji echo 'linux arm5 build completed' arm6: deps GOARM=6 gox $(LDFLAGS) -os="linux" -arch="arm" -output=$(BUILDDIR)/arm6/fuji/fuji-gw $(REPO) - cp -p packages/config.simple.ini.example $(BUILDDIR)/arm6/fuji/config.ini.example + cp -p packages/config.simple.toml.example $(BUILDDIR)/arm6/fuji/config.toml.example cd $(BUILDDIR)/arm6/ && tar zcvf ../../$(ARTIFACTS)/fuji-gw_$(TAG)_arm6.tar.gz fuji echo 'linux arm6 build completed' arm7: deps GOARM=7 gox $(LDFLAGS) -os="linux" -arch="arm" -output=$(BUILDDIR)/arm7/fuji/fuji-gw $(REPO) - cp -p packages/config.simple.ini.example $(BUILDDIR)/arm7/fuji/config.ini.example + cp -p packages/config.simple.toml.example $(BUILDDIR)/arm7/fuji/config.toml.example cd $(BUILDDIR)/arm7/ && tar zcvf ../../$(ARTIFACTS)/fuji-gw_$(TAG)_arm7.tar.gz fuji echo 'linux arm7 build completed' linux_386: deps gox $(LDFLAGS) -os="linux" -arch="386" -output=$(BUILDDIR)/linux_386/fuji/fuji-gw $(REPO) - cp -p packages/config.simple.ini.example $(BUILDDIR)/linux_386/fuji/config.ini.example + cp -p packages/config.simple.toml.example $(BUILDDIR)/linux_386/fuji/config.toml.example cd $(BUILDDIR)/linux_386/ && tar zcvf ../../$(ARTIFACTS)/fuji-gw_$(TAG)_linux_386.tar.gz fuji echo 'linux 386 build completed' linux_amd64: deps gox $(LDFLAGS) -os="linux" -arch="amd64" -output=$(BUILDDIR)/linux_amd64/fuji/fuji-gw $(REPO) - cp -p packages/config.simple.ini.example $(BUILDDIR)/linux_amd64/fuji/config.ini.example + cp -p packages/config.simple.toml.example $(BUILDDIR)/linux_amd64/fuji/config.toml.example cd $(BUILDDIR)/linux_amd64/ && tar zcvf ../../$(ARTIFACTS)/fuji-gw_$(TAG)_linux_amd64.tar.gz fuji echo 'linux amd64 build completed' # freebsd_amd64: deps # gox $(LDFLAGS) -os="freebsd" -arch="amd64" -output=$(BUILDDIR)/freebsd_amd64/fuji/fuji-gw $(REPO) -# cp -p packages/config.simple.ini.example $(BUILDDIR)/freebsd_amd64/fuji/config.ini.example +# cp -p packages/config.simple.toml.example $(BUILDDIR)/freebsd_amd64/fuji/config.toml.example # cd $(BUILDDIR)/freebsd_amd64/ && tar zcvf ../../$(ARTIFACTS)/fuji-gw_$(TAG)_freebsd_amd64.tar.gz fuji # echo 'freebsd amd64 build completed' # darwin_amd64: deps # gox $(LDFLAGS) -os="darwin" -arch="amd64" -output=$(BUILDDIR)/darwin/fuji/fuji-gw $(REPO) -# cp -p packages/config.simple.ini.example $(BUILDDIR)/darwin/fuji/config.ini.example +# cp -p packages/config.simple.toml.example $(BUILDDIR)/darwin/fuji/config.toml.example # cd $(BUILDDIR)/darwin/ && tar zcvf ../../$(ARTIFACTS)/fuji-gw_$(TAG)_darwin_amd64.tar.gz fuji # echo 'darwin amd64 build completed' @@ -87,7 +88,7 @@ mkdir -p $(BUILDDIR)/packages_raspi/etc/fuji-gw mkdir -p $(BUILDDIR)/packages_raspi/etc/init.d cp -p $(BUILDDIR)/arm6/fuji/fuji-gw $(BUILDDIR)/packages_raspi/usr/local/bin/fuji-gw - cp -p packages/config.simple.ini.example $(BUILDDIR)/packages_raspi/etc/fuji-gw/config.ini + cp -p packages/config.simple.toml.example $(BUILDDIR)/packages_raspi/etc/fuji-gw/config.toml cp -p packages/fuji-gw.init $(BUILDDIR)/packages_raspi/etc/init.d/ cd $(BUILDDIR)/packages_raspi; $(FPM) -s dir -t deb -a armhf -n fuji-gw -v $(TAG) -p ../../$(ARTIFACTS) --deb-init ./etc/init.d/fuji-gw.init . mv $(ARTIFACTS)/fuji-gw_$(TAG)_armhf.deb $(ARTIFACTS)/fuji-gw_$(TAG)_raspi_arm6.deb @@ -98,7 +99,7 @@ mkdir -p $(BUILDDIR)/packages_raspi2/usr/local/bin mkdir -p $(BUILDDIR)/packages_raspi2/etc/fuji-gw cp -p $(BUILDDIR)/arm7/fuji/fuji-gw $(BUILDDIR)/packages_raspi2/usr/local/bin/fuji-gw - cp -p packages/config.simple.ini.example $(BUILDDIR)/packages_raspi2/etc/fuji-gw/config.ini + cp -p packages/config.simple.toml.example $(BUILDDIR)/packages_raspi2/etc/fuji-gw/config.toml cd $(BUILDDIR)/packages_raspi2; $(FPM) -s dir -t deb -a armhf -n fuji-gw -v $(TAG) -p ../../$(ARTIFACTS) . mv $(ARTIFACTS)/fuji-gw_$(TAG)_armhf.deb $(ARTIFACTS)/fuji-gw_$(TAG)_raspi2_arm7.deb @@ -108,7 +109,7 @@ mkdir -p $(BUILDDIR)/packages_armadillo/usr/local/bin mkdir -p $(BUILDDIR)/packages_armadillo/etc/fuji-gw cp -p $(BUILDDIR)/arm5/fuji/fuji-gw $(BUILDDIR)/packages_armadillo/usr/local/bin/fuji-gw - cp -p packages/config.simple.ini.example $(BUILDDIR)/packages_armadillo/etc/fuji-gw/config.ini + cp -p packages/config.simple.toml.example $(BUILDDIR)/packages_armadillo/etc/fuji-gw/config.toml cd $(BUILDDIR)/packages_armadillo; $(FPM) -s dir -t deb -a armle -n fuji-gw -v $(TAG) -p .. . edison: linux_386 @@ -118,7 +119,7 @@ mkdir -p $(BUILDDIR)/packages_edison/etc/fuji-gw cp -p $(BUILDDIR)/linux_386/fuji/fuji-gw $(BUILDDIR)/packages_edison/usr/local/bin/fuji-gw - cp -p packages/config.simple.ini.example $(BUILDDIR)/packages_edison/etc/fuji-gw/config.ini + cp -p packages/config.simple.toml.example $(BUILDDIR)/packages_edison/etc/fuji-gw/config.toml mkdir -p $(BUILDDIR)/packages_edison/CONTROL sed -e 's/FUJI_GIT_TAG/$(TAG)/' packages/opkg_files/control.in > packages/opkg_files/control @@ -133,13 +134,13 @@ mkdir -p $(BUILDDIR)/packages_linux_amd64/usr/local/bin mkdir -p $(BUILDDIR)/packages_linux_amd64/etc/fuji-gw cp -p $(BUILDDIR)/linux_amd64/fuji/fuji-gw $(BUILDDIR)/packages_linux_amd64/usr/local/bin/fuji-gw - cp -p packages/config.simple.ini.example $(BUILDDIR)/packages_linux_amd64/etc/fuji-gw/config.ini + cp -p packages/config.simple.toml.example $(BUILDDIR)/packages_linux_amd64/etc/fuji-gw/config.toml cd $(BUILDDIR)/packages_linux_amd64; $(FPM) -s dir -t deb -a x86_64 -n fuji-gw -v $(TAG) -p ../../$(ARTIFACTS) . test: $(ALL_LIST) go get golang.org/x/tools/cmd/cover - go test -coverpkg github.com/shiguredo/fuji ./... + go test -coverpkg github.com/shiguredo/fuji $(TARGETS_NOVENDOR) deps: if [ -d $(ARTIFACTS) ] ; then rm -rf $(ARTIFACTS) ; fi @@ -151,7 +152,7 @@ go get -u github.com/mitchellh/gox go get github.com/kr/pty # go get -u github.com/golang/lint/golint - godep restore + glide install clean: rm -f fuji diff -Nru fuji-0.3.0/message/message.go fuji-1.0.2/message/message.go --- fuji-0.3.0/message/message.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/message/message.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ Topic string } -var ( +const ( TypeSubscribed = "subscribed" ) diff -Nru fuji-0.3.0/message/topicstring.go fuji-1.0.2/message/topicstring.go --- fuji-0.3.0/message/topicstring.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/message/topicstring.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,12 +21,12 @@ validator "gopkg.in/validator.v2" - "github.com/shiguredo/fuji/inidef" + "github.com/shiguredo/fuji/config" ) // init is automatically invoked at initial time. func init() { - validator.SetValidationFunc("validtopic", inidef.ValidMqttPublishTopic) + validator.SetValidationFunc("validtopic", config.ValidMqttPublishTopic) } // TopicString is an type which is represents MQTT Topic string. @@ -34,7 +34,7 @@ Str string `validate:"max=32767,validtopic"` } -func (topic TopicString) Sring() string { +func (topic TopicString) String() string { return fmt.Sprintf("Topic: %s", topic.Str) } @@ -48,11 +48,11 @@ return errors.New("not a valid UTF8 string") } - if inidef.ReU0.FindString(topic.Str) != "" { + if config.ReU0.FindString(topic.Str) != "" { return errors.New("topic should NOT include \\U0000 character") } - if inidef.ReWild.FindString(topic.Str) != "" { + if config.ReWild.FindString(topic.Str) != "" { return errors.New("should not MQTT pub-topic include wildard character") } return nil diff -Nru fuji-0.3.0/message/topicstring_test.go fuji-1.0.2/message/topicstring_test.go --- fuji-0.3.0/message/topicstring_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/message/topicstring_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff -Nru fuji-0.3.0/packages/config.simple.ini.example fuji-1.0.2/packages/config.simple.ini.example --- fuji-0.3.0/packages/config.simple.ini.example 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/packages/config.simple.ini.example 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -[gateway] - - name = ham - - max_retry_count = 7 - retry_interval = 3 # sec - -[broker "sango/1"] - - host = localhost - port = 1883 - - username = YOURUSERNAME - password = YOURPASSWORD - - retry_interval = 10 - topic_prefix = sometextforprefix - - -[device "dora/dummy"] - - broker = sango - qos = 0 - - interval = 10 - payload = Hello world. - subscribe = true - -[status] - - broker = sango - interval = 10 - -[status "cpu"] - - cpu_times = user, system, idle, nice, iowait, irq, softirq, guest - -[status "memory"] - - virtual_memory = total, available, percent, used, free diff -Nru fuji-0.3.0/packages/config.simple.toml.example fuji-1.0.2/packages/config.simple.toml.example --- fuji-0.3.0/packages/config.simple.toml.example 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/packages/config.simple.toml.example 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,44 @@ +[gateway] + + name = "ham" + + max_retry_count = 7 + retry_interval = 3 # sec + +[[broker."sango/1"]] + + host = "localhost" + port = 1883 + + username = "YOURUSERNAME" + password = "YOURPASSWORD" + + retry_interval = 10 + topic_prefix = "sometextforprefix" + + +[device."dora"] + + type = "dummy" + broker = "sango" + qos = 0 + + interval = 30 + payload = "Hello world." + +[status] + + broker = "sango" + interval = 10 + +[[status."cpu"]] + + cpu_times = "user, system, idle, nice, iowait, irq, softirq, guest" + +[[status."memory"]] + + virtual_memory = "total, available, percent, used, free" + +[[status."ip_address"]] + + interface = "all" diff -Nru fuji-0.3.0/packages/fuji-gw.init fuji-1.0.2/packages/fuji-gw.init --- fuji-0.3.0/packages/fuji-gw.init 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/packages/fuji-gw.init 2016-03-23 04:35:15.000000000 +0000 @@ -15,7 +15,7 @@ DAEMON=/usr/local/bin/fuji-gw PIDFILE=/var/run/fuji-gwd.pid -FUJI_GW_CONF=/etc/fuji-gw/config.ini +FUJI_GW_CONF=/etc/fuji-gw/config.toml test -x $DAEMON || exit 5 diff -Nru fuji-0.3.0/README.rst fuji-1.0.2/README.rst --- fuji-0.3.0/README.rst 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/README.rst 2016-03-23 04:35:15.000000000 +0000 @@ -2,7 +2,7 @@ MQTT Gateway: Fuji ########################### -:version: 0.3.0 +:version: 1.0.2 .. image:: https://circleci.com/gh/shiguredo/fuji/tree/develop.svg?style=svg&circle-token=203d959fffaf8dcdc0c68642dde5329e55a47792 :target: https://circleci.com/gh/shiguredo/fuji/tree/develop @@ -39,22 +39,44 @@ Downloads ========= -:URL: https://github.com/shiguredo/fuji/releases/tag/0.3.0 +:URL: https://github.com/shiguredo/fuji/releases/tag/1.0.2 -- `fuji-gw_0.3.0_arm5.tar.gz `_ -- `fuji-gw_0.3.0_arm6.tar.gz `_ -- `fuji-gw_0.3.0_arm7.tar.gz `_ -- `fuji-gw_0.3.0_edison_386.ipk `_ -- `fuji-gw_0.3.0_linux_386.tar.gz `_ -- `fuji-gw_0.3.0_linux_amd64.tar.gz `_ -- `fuji-gw_0.3.0_raspi2_arm7.deb `_ -- `fuji-gw_0.3.0_raspi_arm6.deb `_ +- `fuji-gw_1.0.2_arm5.tar.gz `_ +- `fuji-gw_1.0.2_arm6.tar.gz `_ +- `fuji-gw_1.0.2_arm7.tar.gz `_ +- `fuji-gw_1.0.2_edison_386.ipk `_ +- `fuji-gw_1.0.2_linux_386.tar.gz `_ +- `fuji-gw_1.0.2_linux_amd64.tar.gz `_ +- `fuji-gw_1.0.2_raspi2_arm7.deb `_ +- `fuji-gw_1.0.2_raspi_arm6.deb `_ ChangeLog ========= see `CHANGELOG.rst `_ +Migration Notice +================ + +from version 0.3.0 or under to 1.0.2 +-------------------------------------- + +Configuration file format changed to TOML + +see `config.toml.example `_ + + +Topic of publish/subscribe message changed + +- publish topic format from device :: + + ////publish + +- subscribe topic format to device (currently serial type device only support this functionality) :: + + ////subscribe + + Build ===== @@ -95,7 +117,7 @@ :: - Copyright 2015 Shiguredo Inc. + Copyright 2015-2016 Shiguredo Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff -Nru fuji-0.3.0/tests/connectlocalpub.ini fuji-1.0.2/tests/connectlocalpub.ini --- fuji-0.3.0/tests/connectlocalpub.ini 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/connectlocalpub.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -[gateway] - - name = ham - -[broker "mosquitto/1"] - - host = localhost - port = 1883 - - retry_interval = 10 - - -[device "dora/dummy"] - - broker = mosquitto - qos = 0 - - interval = 10 - payload = connect local pub only Hello world. - - type = EnOcean diff -Nru fuji-0.3.0/tests/connectlocalpubsub.ini fuji-1.0.2/tests/connectlocalpubsub.ini --- fuji-0.3.0/tests/connectlocalpubsub.ini 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/connectlocalpubsub.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -; Copyright 2015 Shiguredo Inc. -; -; Licensed under the Apache License, Version 2.0 (the "License"); -; you may not use this file except in compliance with the License. -; You may obtain a copy of the License at -; -; http://www.apache.org/licenses/LICENSE-2.0 -; -; Unless required by applicable law or agreed to in writing, software -; distributed under the License is distributed on an "AS IS" BASIS, -; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -; See the License for the specific language governing permissions and -; limitations under the License. - - -[gateway] - - name = ham - -[broker "mosquitto/1"] - - host = localhost - port = 1883 - - retry_interval = 10 - - -[device "dora/dummy"] - - broker = mosquitto - qos = 0 - - interval = 10 - payload = connect local pubsub Hello world. - - type = EnOcean diff -Nru fuji-0.3.0/tests/connect_test.go fuji-1.0.2/tests/connect_test.go --- fuji-0.3.0/tests/connect_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/connect_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,23 +19,24 @@ "testing" "time" - MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" + MQTT "github.com/eclipse/paho.mqtt.golang" "github.com/stretchr/testify/assert" "github.com/shiguredo/fuji" "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/device" "github.com/shiguredo/fuji/gateway" - "github.com/shiguredo/fuji/inidef" ) // publish test to broker on localhost // dummydevice is used as a source of published message func TestConnectLocalPub(t *testing.T) { - go fuji.Start("connectlocalpub.ini") + go fuji.Start("connect.toml") time.Sleep(2 * time.Second) + return } // TestConnectLocalPubSub tests @@ -50,7 +51,7 @@ // publised messages confirmed by subscriber // get config - conf, err := inidef.LoadConfig("connectlocalpubsub.ini") + conf, err := config.LoadConfig("connect.toml") assert.Nil(err) // get Gateway @@ -62,7 +63,7 @@ assert.Nil(err) // get DummyDevice - dummyDevice, err := device.NewDummyDevice(conf.Sections[3], brokerList, device.NewDeviceChannel()) + dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, device.NewDeviceChannel()) assert.Nil(err) assert.NotNil(dummyDevice) @@ -73,11 +74,8 @@ opts := MQTT.NewClientOptions() url := fmt.Sprintf("tcp://%s:%d", brokerList[0].Host, brokerList[0].Port) opts.AddBroker(url) - opts.SetClientID(gw.Name) + opts.SetClientID(fmt.Sprintf("prefix%s", gw.Name)) opts.SetCleanSession(false) - opts.SetDefaultPublishHandler(func(client *MQTT.Client, msg MQTT.Message) { - subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} - }) client := MQTT.NewClient(opts) assert.Nil(err) @@ -86,22 +84,21 @@ } qos := 0 - topic := "#" - client.Subscribe(topic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { + expectedTopic := fmt.Sprintf("/%s/%s/%s/publish", gw.Name, dummyDevice.Name, dummyDevice.Type) + expectedMessage := fmt.Sprintf("%s", dummyDevice.Payload) + fmt.Printf("expetcted topic: %s\nexpected message%s", expectedTopic, expectedMessage) + client.Subscribe(expectedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { + subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} }) - // TODO: should be write later - /* - channel := fuji.SetupMQTTChannel(client, gateway, brokerList[0]) - - // Setup DummyDevice to publish test payload - - dummyDevice.Start(channel) - - // wait for 1 publication of dummy worker - message := <-subscriberChannel - assert.Equal("dummy", message) + // wait for 1 publication of dummy worker + select { + case message := <-subscriberChannel: + assert.Equal(expectedTopic, message[0]) + assert.Equal(expectedMessage, message[1]) + case <-time.After(time.Second * 11): + assert.Equal("subscribe completed in 11 sec", "not completed") + } - client.Disconnect(250) - */ + client.Disconnect(20) } diff -Nru fuji-0.3.0/tests/connect.toml fuji-1.0.2/tests/connect.toml --- fuji-0.3.0/tests/connect.toml 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/connect.toml 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,20 @@ +[gateway] + + name = "hamlocalconnect" + +[[broker."mosquitto/1"]] + + host = "localhost" + port = 1883 + + retry_interval = 10 + + +[device."dora"] + + type = "dummy" + broker = "mosquitto" + qos = 0 + + interval = 10 + payload = "connect local pub only Hello world." diff -Nru fuji-0.3.0/tests/ini_retain_test.go fuji-1.0.2/tests/ini_retain_test.go --- fuji-0.3.0/tests/ini_retain_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/ini_retain_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,186 +0,0 @@ -// Copyright 2015 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/device" - "github.com/shiguredo/fuji/inidef" - "github.com/shiguredo/fuji/message" -) - -// iniRetainTestCase はRetain機能のテストの条件を示すデータ型です。 -// iniString は設定ファイルの内容 -// expectedError はテストを実行したときに期待されるエラーの状態 -// message はテストが失敗した内容の説明 -type iniRetainTestCase struct { - iniStr string - expectedError inidef.AnyError - message string -} - -var serialDeviceTestcases = []iniRetainTestCase{ - // check device validation without retain flag - { - iniStr: ` - [broker "sango/1"] - host = localhost - port = 1883 - - [device "hi/serial"] - broker = sango - serial = /dev/tty - baud = 9600 - qos = 0 -`, - expectedError: nil, - message: "Retain flag could not be omitted. Shall be optional."}, - // check device validation with retain flag - { - iniStr: ` - [broker "sango/1"] - host = localhost - port = 1883 - - [device "hi/serial"] - broker = sango - serial = /dev/tty - baud = 9600 - qos = 0 - retain = true - qos = 0 -`, - expectedError: nil, - message: "Retain flag could not be set."}, - // check device validation with retain flag is false - { - iniStr: ` - [broker "sango/1"] - host = localhost - port = 1883 - - [device "hi/serial"] - broker = sango - serial = /dev/tty - baud = 9600 - qos = 0 - retain = false - qos = 0 -`, - expectedError: nil, - message: "Retain flag could not be un-set."}, -} - -var dummyDeviceTestcases = []iniRetainTestCase{ - // check device validation without retain flag - { - iniStr: ` - [broker "sango/1"] - host = localhost - port = 1883 - - [device "hi/dummy"] - broker = sango - qos = 0 - interval = 10 - payload = Hello world. -`, - expectedError: nil, - message: "Retain flag could not be omitted. Shall be optional."}, - // check device validation with retain flag - { - iniStr: ` - [broker "sango/1"] - host = localhost - port = 1883 - - [device "hi/dummy"] - broker = sango - qos = 0 - retain = true - interval = 10 - payload = Hello world. -`, - expectedError: nil, - message: "Retain flag could not be set."}, - // check device validation with retain flag is false - { - iniStr: ` - [broker "sango/1"] - host = localhost - port = 1883 - - [device "hi/dummy"] - broker = sango - qos = 0 - retain = false - interval = 10 - payload = Hello world. -`, - expectedError: nil, - message: "Retain flag could not be un-set."}, -} - -// generalIniRetainSerialDeviceTest checks retain function with serial device -func generalIniRetainSerialDeviceTest(test iniRetainTestCase, t *testing.T) { - assert := assert.New(t) - - conf, err := inidef.LoadConfigByte([]byte(test.iniStr)) - assert.Nil(err) - - brokers, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - - devices, _, err := device.NewDevices(conf, brokers) - assert.Nil(err) - assert.Equal(1, len(devices)) -} - -// generalIniRetainDummyDeviceTest checks retain function with dummy device -func generalIniRetainDummyDeviceTest(test iniRetainTestCase, t *testing.T) { - assert := assert.New(t) - - conf, err := inidef.LoadConfigByte([]byte(test.iniStr)) - assert.Nil(err) - - brokers, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - - dummy, err := device.NewDummyDevice(conf.Sections[2], brokers, device.NewDeviceChannel()) - if test.expectedError == nil { - assert.Nil(err) - assert.NotNil(dummy) - } else { - assert.NotNil(err) - } -} - -// TestIniRetainDeviceAll tests a serial device using test code -func TestIniRetainDeviceAll(t *testing.T) { - for _, testcase := range serialDeviceTestcases { - generalIniRetainSerialDeviceTest(testcase, t) - } -} - -// TestIniRetainDeviceAll tests a dummy device using test code -func TestIniRetainDummyDeviceAll(t *testing.T) { - for _, testcase := range dummyDeviceTestcases { - generalIniRetainDummyDeviceTest(testcase, t) - } -} diff -Nru fuji-0.3.0/tests/ini_test.go fuji-1.0.2/tests/ini_test.go --- fuji-0.3.0/tests/ini_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/ini_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -// Copyright 2015 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/device" - "github.com/shiguredo/fuji/gateway" - "github.com/shiguredo/fuji/inidef" - "github.com/shiguredo/fuji/message" -) - -func TestIniLoadini(t *testing.T) { - assert := assert.New(t) - - _, err := inidef.LoadConfig("testing_conf.ini") - assert.Nil(err) -} - -func TestIniNewGateway(t *testing.T) { - assert := assert.New(t) - - conf, err := inidef.LoadConfig("testing_conf.ini") - assert.Nil(err) - gw, err := gateway.NewGateway(conf) - assert.Nil(err) - assert.Equal("ham", gw.Name) -} - -func TestIniNewBrokers(t *testing.T) { - assert := assert.New(t) - - conf, err := inidef.LoadConfig("testing_conf.ini") - assert.Nil(err) - brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - assert.Equal(3, len(brokerList)) -} - -func TestIniNewSerialDevices(t *testing.T) { - assert := assert.New(t) - - conf, err := inidef.LoadConfig("testing_conf.ini") - brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - deviceList, _, err := device.NewDevices(conf, brokerList) - assert.Nil(err) - assert.Equal(3, len(deviceList)) -} - -func TestIniNewDummyDevice(t *testing.T) { - assert := assert.New(t) - - conf, err := inidef.LoadConfig("testing_conf.ini") - brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - - dummy, err := device.NewDummyDevice(conf.Sections[7], brokerList, device.NewDeviceChannel()) - assert.Nil(err) - assert.Equal("dummy", dummy.DeviceType()) - assert.Equal(2, int(dummy.QoS)) -} diff -Nru fuji-0.3.0/tests/ini_will_test.go fuji-1.0.2/tests/ini_will_test.go --- fuji-0.3.0/tests/ini_will_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/ini_will_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -// Copyright 2015 Shiguredo Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/shiguredo/fuji/broker" - "github.com/shiguredo/fuji/inidef" - "github.com/shiguredo/fuji/message" -) - -type iniWillTestCase struct { - iniStr string // testcase config file - expectedError inidef.AnyError // expected error status - message string // message when failed -} - -var testcases = []iniWillTestCase{ - // tests broker validation without will_message - { - iniStr: ` - [broker "sango/1"] - - host = localhost - port = 1883 -`, - expectedError: nil, - message: "WillMessage could not be omitted. Shall be optional."}, - // tests broker validation with will_message - { - iniStr: ` - [broker "sango/1"] - - host = localhost - port = 1883 - will_message = Hello world. -`, - expectedError: nil, - message: "WillMessage could not be defined."}, - // tests broker validation with empty will_message - { - iniStr: ` - [broker "sango/1"] - - host = localhost - port = 1883 - will_message = "" -`, - expectedError: nil, - message: "Empty WillMessage could not be defined."}, - // tests multiple broker validation with only one will_message - { - iniStr: ` - [broker "sango/1"] - - host = localhost - port = 1883 - - [broker "sango/2"] - - host = 192.168.1.1 - port = 1883 - will_message = Hello world. -`, - expectedError: nil, - message: "WillMessage could not be defined for one of two."}, - // tests multiple broker validation with both will_message - { - iniStr: ` - [broker "sango/1"] - - host = localhost - port = 1883 - will_message = Change the world. - - [broker "sango/2"] - - host = 192.168.1.1 - port = 1883 - will_message = Hello world. -`, - expectedError: nil, - message: "WillMessage could not be defined for both of two."}, -} - -func generalIniWillTest(test iniWillTestCase, t *testing.T) { - assert := assert.New(t) - - conf, err := inidef.LoadConfigByte([]byte(test.iniStr)) - assert.Nil(err) - - brokers, err := broker.NewBrokers(conf, make(chan message.Message)) - assert.Nil(err) - assert.NotEqual(0, len(brokers)) -} - -func TestIniWillAll(t *testing.T) { - for _, testcase := range testcases { - generalIniWillTest(testcase, t) - } -} diff -Nru fuji-0.3.0/tests/mosquitto/ca.key fuji-1.0.2/tests/mosquitto/ca.key --- fuji-0.3.0/tests/mosquitto/ca.key 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/ca.key 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,965D3104A27A8D8D + ++Ek6vaIgZA4wsEcQkzBonm+GXj2yqpn6mLXcXngEp/Z/qYJ/u9zbwiTl6mDsov4M +4FB8qyycIOHmwnmHWNwel/YqUb5i6GYc9eeT3DPE2zgNIUb/hybsEg5j1ux9GU/P +OIrC1bf1Kx+P+S+1Cfy3xCLxwpgr/XUVAlREWgqIDDqoK0paZQm3FLgYyy3Q1efU +IeChXRWi4wYnugPhNSPqr+ZYBTxIbPZwSjk4HnSgXdPkE2ltgfeuDXvM4QYcB04Y +GnHQ7b39wFkb9CUDjZyKQGWx6IN7bTO3TV0aarHnbzwN8doB49ovQZta88kTd99x +8qgKc5ha5uq4YstjcBBVhraG1ZsJi/pg2OdP42N0N5ccWu2QFut28uLlMoBUX6PE +Tw8Bub7AdDpJCVIJo5QzRx4+xhs4EfHUjTbq0R9ZE09qaVBQ1UlG6VMKF5sgrraw +JEQ/cGDM/r84+E3NwLuLJF6fjYooYKgcPu3hVpfjWEK8QanAVNiBo7Uoq5126NLE +fIkPwfnALCLCBzV2N5Yfk1zM4F9d03+PaN4EPrB4dfwoew7zKdXW7AwmEcVT7Z20 +rLTndsjnVkn+7AObaftPB7ex/4uAS8NX0l8Si6o25oQVopU70/FSG4vyESfm4nEl +7aOVOPc9hTdNmHwrwBm92DeTYZC9ZyQ5ofomJW6ZQbhzTYwIsxOf/a5+FIo+HtNs +qLel6I/x8Vd+TN5dwujDkX21pN1jsF/MmrlSDLd09p9jmS0/pK86xy+hrazIbLU5 +oqyvO5OmIUF3GSOGQnKn9C5kDykXsU1vMweeTJhr2iRRXs1VUhX5Pw== +-----END RSA PRIVATE KEY----- diff -Nru fuji-0.3.0/tests/mosquitto/ca.pem fuji-1.0.2/tests/mosquitto/ca.pem --- fuji-0.3.0/tests/mosquitto/ca.pem 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/ca.pem 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICqjCCAhOgAwIBAgIJAKk2CA51YCAVMA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV +BAYTAkpQMRMwEQYDVQQIEwpTb21lLVN0YXRlMRAwDgYDVQQKEwdTb21lT3JnMQ0w +CwYDVQQDEwRyb290MB4XDTE1MTExNjA4MDExMloXDTI1MTExMzA4MDExMlowQzEL +MAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUxEDAOBgNVBAoTB1NvbWVP +cmcxDTALBgNVBAMTBHJvb3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMlL +Gg9sSZzqwNYJxM1+DQ4rkuLQuXg4HOAc6r1d+64PXShroAn+HemJuXP/Z4rInwIj +LYbhYGU1AkCoX/776U61DEAkrioNWdvV3OZiwdgmLL+1tkjQC4QuineRy9xn49N0 +qr2a6qV0gkz4ZM4WnKaGRiLOSyCI5rhagAVLwoFNAgMBAAGjgaUwgaIwHQYDVR0O +BBYEFN7Iif0cRQiYVoWbXhqKI5LkkxGYMHMGA1UdIwRsMGqAFN7Iif0cRQiYVoWb +XhqKI5LkkxGYoUekRTBDMQswCQYDVQQGEwJKUDETMBEGA1UECBMKU29tZS1TdGF0 +ZTEQMA4GA1UEChMHU29tZU9yZzENMAsGA1UEAxMEcm9vdIIJAKk2CA51YCAVMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAwn+DC1gG+O+oTGP4hJESOm6f +IkTYSx4jmyuKqcR6VhLgX3H8bUHyH/B3Oqi8cnhgIhPq+6wf6jyV3KaUio46Jl7E +hG2z3Rz9ZHgBrDrxvkR55ZTOFOf0FCSduxErnWKPllQCOzzLcZEuZAWvRKTM3NQw +XB+OQcJgenRLw9n9cb4= +-----END CERTIFICATE----- diff -Nru fuji-0.3.0/tests/mosquitto/client.csr fuji-1.0.2/tests/mosquitto/client.csr --- fuji-0.3.0/tests/mosquitto/client.csr 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/client.csr 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIClTCCAX0CAQAwUDELMAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUx +GTAXBgNVBAoTEFNPTUVPUkdBTklaQVRJT04xETAPBgNVBAMTCHVzZXJuYW1lMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuRBC17Y+/rgQMagOGqCdH58J +LNv59R8HFHKiawvNJavtwEJRqfLytRwtyXjxalUOe7GlwvBAKiG/h7xE9HqoZzgs +DWYyAEgAyedHxcoGg7ekRBTXUpkLxhxdCJBuUm26WN8PS0VdiCcqXBU5NH0DYPMX +3OCl+Qdf+qEc+2yvN6fJC2up1gJ+FgufC2jaq8zwE77tBEZmWS/r3nk0EO2XFQ/Z +Csz4XOrrKIX3Yq3r3BxWfQh/9ek7Zg0jqj1jjg4spAvsg9qjbfbE5BM/58XZ7EiS +wht/1pMau6pgfEC8obfJU5AbiWrlXP6ERZQqpwbfkKorNnp/bw0EgiszT92y5wID +AQABoAAwDQYJKoZIhvcNAQELBQADggEBAJlzPonKVkhimeMMwpJViHGtOlDOmcrT +0hZIVGh95om4nmz6KcjvnRgHeb/XhgHkbtzOJW6DwxgYA/BGQHEGl/XAVAb5XIgG +P8VN4U5U34dwzJaENuMbJtjx2U5+ZADfRLnj6foTd2vz/pyTfwUixX9rKMQRsgbV +AU4FfEqpqgkh1WckSTgIlP3YaWJhJmgetNSxdFCa36YOhPztEqCRJEKopBXCwupX +mGsdWjWkVyRqhFTjn2M82YKyp+WJGNYwva6akOfeWn0oJ4QchaMJG4s/WvGSP6TN +y2ikm4462WBsbflIdF2c0N0UXScNyHBko0DpGNKzbQC0C2mbETeiguo= +-----END CERTIFICATE REQUEST----- diff -Nru fuji-0.3.0/tests/mosquitto/client.key fuji-1.0.2/tests/mosquitto/client.key --- fuji-0.3.0/tests/mosquitto/client.key 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/client.key 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuRBC17Y+/rgQMagOGqCdH58JLNv59R8HFHKiawvNJavtwEJR +qfLytRwtyXjxalUOe7GlwvBAKiG/h7xE9HqoZzgsDWYyAEgAyedHxcoGg7ekRBTX +UpkLxhxdCJBuUm26WN8PS0VdiCcqXBU5NH0DYPMX3OCl+Qdf+qEc+2yvN6fJC2up +1gJ+FgufC2jaq8zwE77tBEZmWS/r3nk0EO2XFQ/ZCsz4XOrrKIX3Yq3r3BxWfQh/ +9ek7Zg0jqj1jjg4spAvsg9qjbfbE5BM/58XZ7EiSwht/1pMau6pgfEC8obfJU5Ab +iWrlXP6ERZQqpwbfkKorNnp/bw0EgiszT92y5wIDAQABAoIBAHJ4pn/70PeKLyoo +A6Fg3A/lNa2z2+dNa/mv9ts0D49Py95yp0TybEKuzXuj/eCCAFVuy1PLfEUTXv+8 +6wI2pNhEHKulHSSjZSl+kBy+HE15WHhsU8xZsri2bq2PeU4vZWb3guRSYcqIP2F6 +F0pqUZ60f3w20TM65pmG8wBqd+96Igb4pU2h+ZerqqEHxwt7lN7aSjgRiD0jEK+N +PeeXHVVLuXVwL8zlPScZMCh64RXtkyJ1/a9+9U60LYWjuYs8IGrGBsX2rizbqi7L +OjeZ6jO4IvlCBruLMMJ4aoUf+OgIlSoqfcpZ5KlY0D3W3vlXTpAYrG+kRTYTqpbc +fOastgECgYEA5AkVExYsLGXbOJaDb+Ptkx3YtXPQkHe3xVYc4jxC5DR0zSThixIC +S+KL0B2vfhZy9SCdSOJ/F+/lAs0InNsP/G2oF0cuop1rQdn3GAbOiyiASvjL8PnP +LUmQhEburxfsfam3OZFwKGveNqA/pCkoQ98eBx7QMbWq59C2Cuw8rWcCgYEAz8If +V8yPblxhVw5cu8HU086prJFIZyksyaWWUhP84IuZJa52hvzy8M+xostSQfc7D+V/ +w3AKNSiSuabgSSmN0f+pLNosSVb36N+QFNCPBaBDqOP97fuIZlslCBaWm+etVE90 +oAJDKllNglWm/rQwoPoJWklME9aNpNe1HkPd3oECgYEAs3jieU8uHRNdYkAz2lBN +n0gSU11/fPR8Unff67759pnCg+LPEKFv5UG8QGPcxyPr/jlZERASb0iDuZyddraC +8m1rqkZ/0cSLshxWeTaCQMvzjQ4blOFHyaDoePNKz8vIeW6lok1xNJ8RGXUuIYmz +AxgLjhcWTMlqZWDCpf4gE2kCgYEAx5hl6EHcYlhaI/rmWHOldj+LfwCsoH9MSgXN +XtlZDpjO7wanVJRbCcNfk1jmk/1jPqhrkGVpSRzLqZSK0X8cgu2tqCuKdIMa9R0j +HPwpC2ym0/EFmccXic5yy0x4MRvox6D2GGtT/7F/54FGSFjwhxbwOU9FyaFMv1uE +46ir1QECgYB0KnNQI4OLffaxnod8qsrSIC4muaXn3AFIKz76isQ5L6VSh+SZVHFe +0P6q6XURsmlD8hZwdMMYN1OV0k9lrI2F5KeGs9B28P1RTM3cN5PhYgmVf3HNQU4N +qcJW6ilH/dpBsyw7v5zrV5+MCDKiHPq0HGBn+Ea6vM7XxSJP3wE0jQ== +-----END RSA PRIVATE KEY----- diff -Nru fuji-0.3.0/tests/mosquitto/client.pem fuji-1.0.2/tests/mosquitto/client.pem --- fuji-0.3.0/tests/mosquitto/client.pem 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/client.pem 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICjjCCAfcCCQC25uKBpE2iKzANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJK +UDETMBEGA1UECBMKU29tZS1TdGF0ZTEQMA4GA1UEChMHU29tZU9yZzENMAsGA1UE +AxMEcm9vdDAeFw0xNTExMTYwODA3NDlaFw0xNjExMTUwODA3NDlaMFAxCzAJBgNV +BAYTAkpQMRMwEQYDVQQIEwpTb21lLVN0YXRlMRkwFwYDVQQKExBTT01FT1JHQU5J +WkFUSU9OMREwDwYDVQQDEwh1c2VybmFtZTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBALkQQte2Pv64EDGoDhqgnR+fCSzb+fUfBxRyomsLzSWr7cBCUany +8rUcLcl48WpVDnuxpcLwQCohv4e8RPR6qGc4LA1mMgBIAMnnR8XKBoO3pEQU11KZ +C8YcXQiQblJtuljfD0tFXYgnKlwVOTR9A2DzF9zgpfkHX/qhHPtsrzenyQtrqdYC +fhYLnwto2qvM8BO+7QRGZlkv6955NBDtlxUP2QrM+Fzq6yiF92Kt69wcVn0If/Xp +O2YNI6o9Y44OLKQL7IPao232xOQTP+fF2exIksIbf9aTGruqYHxAvKG3yVOQG4lq +5Vz+hEWUKqcG35CqKzZ6f28NBIIrM0/dsucCAwEAATANBgkqhkiG9w0BAQUFAAOB +gQAWajbip5KzoaxcbT7N5SYPDjLC8eoTxHQkwUPhiPSGMhHxWyGR9Z2LfD05EAcR +0ZFFWFm+InNizxJHPP5p2zA+1k0XdyphkHhVMPKT8XKj8+xMrNBPxflRiu0iDoO1 +UJoNHHO7MxoLUYhLxHIyXUTeorvA2g5a6mYyPjeJ7wxorA== +-----END CERTIFICATE----- diff -Nru fuji-0.3.0/tests/mosquitto/mosquitto.conf fuji-1.0.2/tests/mosquitto/mosquitto.conf --- fuji-0.3.0/tests/mosquitto/mosquitto.conf 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/mosquitto.conf 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,21 @@ +user mosquitto +log_dest file /mosquitto/mosquitto.log +log_timestamp true +log_type all + +listener 1883 + +listener 8883 +cafile /mosquitto/ca.pem +certfile /mosquitto/server.pem +keyfile /mosquitto/server.key +require_certificate false + +listener 9883 +cafile /mosquitto/ca.pem +certfile /mosquitto/server.pem +keyfile /mosquitto/server.key +require_certificate true + +listener 8080 +protocol websockets diff -Nru fuji-0.3.0/tests/mosquitto/server.csr fuji-1.0.2/tests/mosquitto/server.csr --- fuji-0.3.0/tests/mosquitto/server.csr 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/server.csr 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIChTCCAW0CAQAwQDELMAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUx +EDAOBgNVBAoTB1NvbWVPcmcxCjAIBgNVBAMUASowggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQC3F7oL97GoSnwyWu3FNZGpJQhLhcHPqgSn7tH+mc6rcuYI +zoaIob9A0Km1KC1g5XzE9DRmznwGDVyGtLbrtauELxVteJiESWOKb3T/D98ay09c +ETz+EHDaUmVkKueQyZkUVTgJf0v/n+oSXF44CAZYFm89019qk6lt2XED9I2rCXl+ +ngDQaN3HLcHyzEfNSkEqXX0R4W6UojuoCu27h8pCe1PEwuBzMM2NcTXg6abdxTRT +Uy1r02PIQ2bpRRl5zGwJYzosw2LzfCNvy62JvMaxsW4aZhxKhFJ81U6uXCj2+bSI +M16xGyZ5D4x58qO29McQZSWfUAhkhOpwkV9lTHAbAgMBAAGgADANBgkqhkiG9w0B +AQsFAAOCAQEAKkmC35InxJ2s/jutm0fBmvdBcSZt/ta1qUrWq3wEVroJuEENb8G1 +PZ86+dxxfenDw42Uj2vV/ndTVO6NBOEfxhu2fLlFdY8CL3z3R2UbSQ0AcRD4guKE +PA4dTOiLJYi93ld2qgKb11tT7uysMCnhDcgl2zoCZcqaTM+0QryQsC1i/pPkT6yP +ulikkel/28bz0+Wgi9lUltlF3lRfk3EwBqdZggX4YdEyzq6IfRYo5JyDNQ5t4NAX +2mbYhBuwCZY4LFCARuvum2AWctTfCVdDMlkV99RKobh0aTCozD9Qbp4tjvcdN63b +fMWP0yZS0vwinPzmP+aOl06YcNibqFyebA== +-----END CERTIFICATE REQUEST----- diff -Nru fuji-0.3.0/tests/mosquitto/server.key fuji-1.0.2/tests/mosquitto/server.key --- fuji-0.3.0/tests/mosquitto/server.key 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/server.key 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAtxe6C/exqEp8MlrtxTWRqSUIS4XBz6oEp+7R/pnOq3LmCM6G +iKG/QNCptSgtYOV8xPQ0Zs58Bg1chrS267WrhC8VbXiYhEljim90/w/fGstPXBE8 +/hBw2lJlZCrnkMmZFFU4CX9L/5/qElxeOAgGWBZvPdNfapOpbdlxA/SNqwl5fp4A +0Gjdxy3B8sxHzUpBKl19EeFulKI7qArtu4fKQntTxMLgczDNjXE14Omm3cU0U1Mt +a9NjyENm6UUZecxsCWM6LMNi83wjb8utibzGsbFuGmYcSoRSfNVOrlwo9vm0iDNe +sRsmeQ+MefKjtvTHEGUln1AIZITqcJFfZUxwGwIDAQABAoIBAQCxgJ8t2wSxUwT1 +DJJXDogYo35XOWWcHghFhpKvcg2aydmZ0B89dxIjlCfzKPBVcCZ2CwqCYMx8UZfS +QIDWI1oU3FC5wKCcH0oRe9zBKnHxWAmoCE5JQUcnYZpKcg3toIR34eZhzrevKymS +g1oUmDMOUzGljraCbIVlqdiXLQ/rL67OKHFZP4qEbCqEv8eIBEKMAL7E7S6PAuqa +gMCter26fMvEJADheBIyqTc63Pz/XJIJCLFdySl3WYv69IHnLcXB/oQngo/anjb2 +LbDwxyxZfkiJWfEa8RtL2qWoOsrfuzGICEz0TG6gA+5ZIW9hmrihI/fh7QKvtEJD +/+EqgogBAoGBAOzf9lfVqe9j2VK6KkQUgdjp9JrtyCbyI8ooEToXuEmwjFz9vwyi +pEJgzNvorHZrGZ+pmUg12R877g6WcYOxW9dnGR/LDdcE9cjfUYt3104sE212z1SC +2lOywhrmGwlG/jkS/tK4WrLm8jBNEaxA4vB6VvVI1WLiBb6+3SQMzsHBAoGBAMXg +H+TMY+NZHfa6XT4pjaKHcIL22+SQTuRkJOoOt0gj2GAMgwBW7WxhVJDAIqlWyCJW ++KUKKW29o4fRX7/2RwLwRxzfIrmFg+XL1TJi5jEGYVSb+MsMUBpDw/c8W7x+guxT +xYOKSAO78ZfiSncoqwk1sL09Ya3W20lhXngpOLDbAoGAUP2itRWRLRDu1aJhoTWB +0DDuOarjrK1OH2jjuwExOcDrvT/leuSBVVDTur0rerHT6QuMJWyD+HH9S2+VEHor +9NKDfKNo8AP6Jdx1fUJUk53uZpcg/Lxg+g084QWcaOelNM6R4mq2WEUuueUgDc2B +yseJxARLMawmWrnX0uOuLgECgYBh1Y2PX2sn1kEVY1GE0aDAsjxz1EAmgx8ul0EV +JI+EMIzj+Guw+EnNY1Yfd4/rsAelyuCHIT4Yj0HSfjfcPpUfo9NVOBIALj5nmN9h +WTq9FI18+t0I756PTeAPVp141gg/dq/aeL1gc0VhNjZhMg9Wr2AiQL4R6IBliKnf +uWnZLwKBgHfyg1w+dEUN/WDqJiRAxXkssgACrndXn/2eWbntKOkyO7Ux2HOTPtwg +EofsDDa6Ltln9irqhbsjj2HLCWhF33OioqtWjWYfw66swfmH7qM/iZ+6pTKnsqdx +VvtEEP0chZPhJI6CLIfIBQ3CDdBSrY1RY1E6b7csYQz9jfU6aq5T +-----END RSA PRIVATE KEY----- diff -Nru fuji-0.3.0/tests/mosquitto/server.pem fuji-1.0.2/tests/mosquitto/server.pem --- fuji-0.3.0/tests/mosquitto/server.pem 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/mosquitto/server.pem 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICfjCCAecCCQC25uKBpE2iKjANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJK +UDETMBEGA1UECBMKU29tZS1TdGF0ZTEQMA4GA1UEChMHU29tZU9yZzENMAsGA1UE +AxMEcm9vdDAeFw0xNTExMTYwODA1MDBaFw0yNTExMTMwODA1MDBaMEAxCzAJBgNV +BAYTAkpQMRMwEQYDVQQIEwpTb21lLVN0YXRlMRAwDgYDVQQKEwdTb21lT3JnMQow +CAYDVQQDFAEqMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtxe6C/ex +qEp8MlrtxTWRqSUIS4XBz6oEp+7R/pnOq3LmCM6GiKG/QNCptSgtYOV8xPQ0Zs58 +Bg1chrS267WrhC8VbXiYhEljim90/w/fGstPXBE8/hBw2lJlZCrnkMmZFFU4CX9L +/5/qElxeOAgGWBZvPdNfapOpbdlxA/SNqwl5fp4A0Gjdxy3B8sxHzUpBKl19EeFu +lKI7qArtu4fKQntTxMLgczDNjXE14Omm3cU0U1Mta9NjyENm6UUZecxsCWM6LMNi +83wjb8utibzGsbFuGmYcSoRSfNVOrlwo9vm0iDNesRsmeQ+MefKjtvTHEGUln1AI +ZITqcJFfZUxwGwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAKEE6zsYjrvl4MTAyx7f +aV0upT+aqHaxBUPH4RkhHxWOqz6Ov9Xk06rafPh0ujry5IMPyFJ9Hi9UrFHoOMtB +UUtdWe6whJUZhRSj+HSak1yCverLC/10jHfcqo2KnBrY1h+RIY2LcmspRayxe+Yj +FAIihOL+maxgu5vlrrE3fmjG +-----END CERTIFICATE----- diff -Nru fuji-0.3.0/tests/retain_test.go fuji-1.0.2/tests/retain_test.go --- fuji-0.3.0/tests/retain_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/retain_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,14 +19,14 @@ "testing" "time" - MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" + MQTT "github.com/eclipse/paho.mqtt.golang" "github.com/stretchr/testify/assert" "github.com/shiguredo/fuji" "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/device" "github.com/shiguredo/fuji/gateway" - "github.com/shiguredo/fuji/inidef" ) // TestRetainJustPublish tests @@ -34,29 +34,31 @@ // 2. send data with retaind flag dummy device normaly func TestRetainJustPublish(t *testing.T) { assert := assert.New(t) - iniStr := ` + + configStr := ` [gateway] - name = retainham + name = "retainham" - [broker "local/1"] + [[broker."local/1"]] - host = localhost + host = "localhost" port = 1883 - [device "doraretain/dummy"] + [device."doraretain"] - broker = local + type = "dummy" + broker = "local" qos = 0 interval = 10 - payload = Hello world retain true. - - type = EnOcean + payload = "Hello world retain true." retain = true ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + + conf, err := config.LoadConfigByte([]byte(configStr)) assert.Nil(err) + commandChannel := make(chan string) go fuji.StartByFileWithChannel(conf, commandChannel) @@ -71,30 +73,70 @@ // 5. subscirbe and receive data func TestRetainSubscribePublishClose(t *testing.T) { assert := assert.New(t) - iniStr := ` + configStr := ` [gateway] - name = testRetainafterclose + name = "testRetainafterclose" - [broker "local/1"] + [[broker."local/1"]] - host = localhost + host = "localhost" port = 1883 - [device "dora/dummy"] + [device."dora"] - broker = local + type = "dummy" + broker = "local" qos = 0 interval = 10 - payload = Hello retained world to subscriber after close. + payload = "Hello retained world to subscriber after close." - type = EnOcean retain = true ` - commandChannel := make(chan string) - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) assert.Nil(err) + isRetain := true + generalPubSubTest(t, conf, isRetain) +} + +// TestNoRetainSubscribePublishClose +// 1. connect gateway to local broker +// 2. send data without retaind flag from dummy device +// 3. disconnect +// 4. reconnect +// 5. subscirbe and receive data +func TestNoRetainSubscribePublishClose(t *testing.T) { + assert := assert.New(t) + configStr := ` + [gateway] + + name = "testNoRetainafterclose" + + [[broker."local/1"]] + + host = "localhost" + port = 1883 + + [device."dora"] + + type = "dummy" + broker = "local" + qos = 0 + + interval = 10 + payload = "Hello retained world to subscriber after close." +` + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + isRetain := false + generalPubSubTest(t, conf, isRetain) +} + +func generalPubSubTest(t *testing.T, conf config.Config, isRetain bool) { + assert := assert.New(t) + + commandChannel := make(chan string) go fuji.StartByFileWithChannel(conf, commandChannel) gw, err := gateway.NewGateway(conf) @@ -109,7 +151,7 @@ devChan := device.NewDeviceChannel() gw.DeviceChannels = append(gw.DeviceChannels, devChan) - dummyDevice, err := device.NewDummyDevice(conf.Sections[3], brokerList, devChan) + dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, devChan) if err != nil { t.Error("Cannot make DummyDeviceList") } @@ -123,25 +165,36 @@ time.Sleep(2 * time.Second) subscriberChannel, err := setupRetainSubscriber(gw, brokerList[0], &dummyDevice) - if err != inidef.Error("") { + if err != config.Error("") { t.Error(err) } - // check Retained message - retainedMessage := <-subscriberChannel - retainedTopic := retainedMessage[0] - retainedPayload := retainedMessage[1] - - expectedTopic := fmt.Sprintf("%s/%s/%s/%s", brokerList[0].TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) - expectedPayload := dummyDevice.Payload - assert.Equal(expectedTopic, retainedTopic) - assert.Equal(expectedPayload, retainedPayload) + // check Retained message + select { + case retainedMessage := <-subscriberChannel: + if !isRetain { + assert.Equal("retained message arrived", "no retain message shall come") + } + retainedTopic := retainedMessage[0] + retainedPayload := retainedMessage[1] + + expectedTopic := fmt.Sprintf("%s/%s/%s/%s/publish", brokerList[0].TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) + expectedPayload := dummyDevice.Payload + + assert.Equal(expectedTopic, retainedTopic) + assert.Equal(expectedPayload, retainedPayload) + + case <-time.After(time.Second * 2): + if isRetain { + assert.Equal("subscribe completed in 11 sec", "not completed") + } + } }() time.Sleep(5 * time.Second) } // setupRetainSubscriber returnes channel in order to read messages with retained flag -func setupRetainSubscriber(gw *gateway.Gateway, broker *broker.Broker, dummyDevice *device.DummyDevice) (chan [2]string, inidef.Error) { +func setupRetainSubscriber(gw *gateway.Gateway, broker *broker.Broker, dummyDevice *device.DummyDevice) (chan [2]string, config.Error) { // Setup MQTT pub/sub client to confirm published content. // messageOutputChannel := make(chan [2]string) @@ -157,16 +210,16 @@ client := MQTT.NewClient(opts) if client == nil { - return nil, inidef.Error("NewClient failed") + return nil, config.Error("NewClient failed") } if token := client.Connect(); token.Wait() && token.Error() != nil { - return nil, inidef.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) + return nil, config.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) } qos := 0 - retainedTopic := fmt.Sprintf("%s/%s/%s/%s", broker.TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) + retainedTopic := fmt.Sprintf("%s/%s/%s/%s/publish", broker.TopicPrefix, gw.Name, dummyDevice.Name, dummyDevice.Type) client.Subscribe(retainedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { }) - return messageOutputChannel, inidef.Error("") + return messageOutputChannel, config.Error("") } diff -Nru fuji-0.3.0/tests/testing_conf.ini fuji-1.0.2/tests/testing_conf.ini --- fuji-0.3.0/tests/testing_conf.ini 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/testing_conf.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -[gateway] - - name = ham - -[broker "sango/1"] - - host = 192.0.2.10 - port = 1883 - - username = fuji-gw - password = 123 - - topic_prefix = fuji-gw@example.com - retry_interval = 10 - - -[broker "sango/2"] - - host = 192.0.2.11 - port = 1883 - - username = fuji-gw - password = 123 - - topic_prefix = fuji-gw@example.com - retry_interval = 10 - -[broker "akane"] - - host = 192.0.2.20 - port = 8883 - tls = true - cert = /path/to/cert - - username = fuji-gw - password = 456 - -[device "spam/serial"] - - broker = sango - qos = 0 - - serial = /dev/tty.ble - baud = 9600 - size = 4 - type = BLE - -[device "beacon/serial"] - - broker = sango - qos = 2 - - serial = /dev/tty.enocean - baud = 115200 - size = 8 - type = EnOcean - -[device "dora/dummy"] - - broker = sango - qos = 2 - - interval = 10 - payload = Hello world. - type = BLE diff -Nru fuji-0.3.0/tests/testing_conf.toml fuji-1.0.2/tests/testing_conf.toml --- fuji-0.3.0/tests/testing_conf.toml 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/testing_conf.toml 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,66 @@ +[gateway] + + name = "ham" + max_retry_count = 30 + +[[broker."sango/1"]] + + host = "192.0.2.10" + port = 1883 + + username = "fuji-gw" + password = "123" + + topic_prefix = "fuji-gw@example.com" + retry_interval = 10 + + +[[broker."sango/2"]] + + host = "192.0.2.11" + port = 1883 + + username = "fuji-gw" + password = 123 + + topic_prefix = "fuji-gw@example.com" + retry_interval = 10 + +[[broker."akane"]] + + host = "192.0.2.20" + port = 8883 + tls = true + cacert = "mosquitto/ca.pem" + + username = "fuji-gw" + password = 456 + +[device."spam"] + + type = "serial" + broker = "sango" + qos = 0 + + serial = "/dev/tty.ble" + baud = 9600 + size = 4 + +[device."beacon"] + + type = "serial" + broker = "sango" + qos = 2 + + serial = "/dev/tty.enocean" + baud = 115200 + size = 8 + +[device."dora"] + + type = "dummy" + broker = "sango" + qos = 2 + + interval = 10 + payload = "Hello world." diff -Nru fuji-0.3.0/tests/tls_clientcert_test.go fuji-1.0.2/tests/tls_clientcert_test.go --- fuji-0.3.0/tests/tls_clientcert_test.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/tls_clientcert_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,138 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "testing" + "time" + + MQTT "github.com/eclipse/paho.mqtt.golang" + "github.com/stretchr/testify/assert" + + "github.com/shiguredo/fuji" + "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" + "github.com/shiguredo/fuji/device" + "github.com/shiguredo/fuji/gateway" +) + +var tlsClientCertconfigStr = ` +[gateway] + + name = "tlsccerthamlocalconnect" + +[[broker."mosquitto/1"]] + + host = "localhost" + port = 9883 + tls = true + cacert = "mosquitto/ca.pem" + client_cert = "mosquitto/client.pem" + client_key = "mosquitto/client.key" + + retry_interval = 10 + + +[device."dora"] + type = "dummy" + + broker = "mosquitto" + qos = 0 + + interval = 10 + payload = "connect local pub only Hello world." +` + +// TestTLSConnectLocalPub +func TestTLSClientCertConnectLocalPub(t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfigByte([]byte(tlsClientCertconfigStr)) + assert.Nil(err) + commandChannel := make(chan string) + go fuji.StartByFileWithChannel(conf, commandChannel) + time.Sleep(2 * time.Second) + +} + +// TestTLSConnectLocalPubSub +// 1. connect gateway to local broker with TLS +// 2. send data from dummy +// 3. check subscribe +func TestTLSClientCertConnectLocalPubSub(t *testing.T) { + assert := assert.New(t) + + // pub/sub test to broker on localhost + // dummydevice is used as a source of published message + // publised messages confirmed by subscriber + + // get config + conf, err := config.LoadConfigByte([]byte(tlsClientCertconfigStr)) + assert.Nil(err) + + // get Gateway + gw, err := gateway.NewGateway(conf) + assert.Nil(err) + + // get Broker + brokerList, err := broker.NewBrokers(conf, gw.BrokerChan) + assert.Nil(err) + + // get DummyDevice + dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, device.NewDeviceChannel()) + assert.Nil(err) + assert.NotNil(dummyDevice) + + // Setup MQTT pub/sub client to confirm published content. + // + subscriberChannel := make(chan [2]string) + + opts := MQTT.NewClientOptions() + url := fmt.Sprintf("ssl://%s:%d", brokerList[0].Host, brokerList[0].Port) + opts.AddBroker(url) + opts.SetClientID(fmt.Sprintf("prefix%s", gw.Name)) + opts.SetCleanSession(false) + + tlsConfig, err := broker.NewTLSConfig(brokerList[0]) + assert.Nil(err) + opts.SetTLSConfig(tlsConfig) + + client := MQTT.NewClient(opts) + assert.Nil(err) + if token := client.Connect(); token.Wait() && token.Error() != nil { + assert.Nil(token.Error()) + t.Log(token.Error()) + } + + qos := 0 + expectedTopic := fmt.Sprintf("/%s/%s/%s/publish", gw.Name, dummyDevice.Name, dummyDevice.Type) + expectedMessage := fmt.Sprintf("%s", dummyDevice.Payload) + t.Logf("expetcted topic: %s\nexpected message%s", expectedTopic, expectedMessage) + client.Subscribe(expectedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { + subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} + }) + + // wait for 1 publication of dummy worker + select { + case message := <-subscriberChannel: + assert.Equal(expectedTopic, message[0]) + assert.Equal(expectedMessage, message[1]) + case <-time.After(time.Second * 11): + assert.Equal("subscribe completed in 11 sec", "not completed") + } + + client.Disconnect(20) +} diff -Nru fuji-0.3.0/tests/tls_connect_test.go fuji-1.0.2/tests/tls_connect_test.go --- fuji-0.3.0/tests/tls_connect_test.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/tls_connect_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,136 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "testing" + "time" + + MQTT "github.com/eclipse/paho.mqtt.golang" + "github.com/stretchr/testify/assert" + + "github.com/shiguredo/fuji" + "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" + "github.com/shiguredo/fuji/device" + "github.com/shiguredo/fuji/gateway" +) + +var configStr = ` +[gateway] + + name = "hamlocalconnect" + +[[broker."mosquitto/1"]] + + host = "localhost" + port = 8883 + tls = true + cacert = "mosquitto/ca.pem" + + retry_interval = 10 + + +[device."dora"] + type = "dummy" + + broker = "mosquitto" + qos = 0 + + interval = 10 + payload = "connect local pub only Hello world." +` + +// TestTLSConnectLocalPub +func TestTLSConnectLocalPub(t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + commandChannel := make(chan string) + go fuji.StartByFileWithChannel(conf, commandChannel) + time.Sleep(2 * time.Second) + +} + +// TestTLSConnectLocalPubSub +// 1. connect gateway to local broker with TLS +// 2. send data from dummy +// 3. check subscribe +func TestTLSConnectLocalPubSub(t *testing.T) { + assert := assert.New(t) + + // pub/sub test to broker on localhost + // dummydevice is used as a source of published message + // publised messages confirmed by subscriber + + // get config + conf, err := config.LoadConfigByte([]byte(configStr)) + assert.Nil(err) + + // get Gateway + gw, err := gateway.NewGateway(conf) + assert.Nil(err) + + // get Broker + brokerList, err := broker.NewBrokers(conf, gw.BrokerChan) + assert.Nil(err) + + // get DummyDevice + dummyDevice, err := device.NewDummyDevice(conf.Sections[2], brokerList, device.NewDeviceChannel()) + assert.Nil(err) + assert.NotNil(dummyDevice) + + // Setup MQTT pub/sub client to confirm published content. + // + subscriberChannel := make(chan [2]string) + + opts := MQTT.NewClientOptions() + url := fmt.Sprintf("ssl://%s:%d", brokerList[0].Host, brokerList[0].Port) + opts.AddBroker(url) + opts.SetClientID(fmt.Sprintf("prefix%s", gw.Name)) + opts.SetCleanSession(false) + + tlsConfig, err := broker.NewTLSConfig(brokerList[0]) + assert.Nil(err) + opts.SetTLSConfig(tlsConfig) + + client := MQTT.NewClient(opts) + assert.Nil(err) + if token := client.Connect(); token.Wait() && token.Error() != nil { + assert.Nil(token.Error()) + t.Log(token.Error()) + } + + qos := 0 + expectedTopic := fmt.Sprintf("/%s/%s/%s/publish", gw.Name, dummyDevice.Name, dummyDevice.Type) + expectedMessage := fmt.Sprintf("%s", dummyDevice.Payload) + t.Logf("expetcted topic: %s\nexpected message%s", expectedTopic, expectedMessage) + client.Subscribe(expectedTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { + subscriberChannel <- [2]string{msg.Topic(), string(msg.Payload())} + }) + + // wait for 1 publication of dummy worker + select { + case message := <-subscriberChannel: + assert.Equal(expectedTopic, message[0]) + assert.Equal(expectedMessage, message[1]) + case <-time.After(time.Second * 11): + assert.Equal("subscribe completed in 11 sec", "not completed") + } + + client.Disconnect(20) +} diff -Nru fuji-0.3.0/tests/toml_retain_test.go fuji-1.0.2/tests/toml_retain_test.go --- fuji-0.3.0/tests/toml_retain_test.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/toml_retain_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,192 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" + "github.com/shiguredo/fuji/device" + "github.com/shiguredo/fuji/message" +) + +// configRetainTestCase indicates a condition for testing Retain. +// configString is the body of configuration file. +// expectedError is the expected error state when the test is executed. +// message is the detail of test failure. +type configRetainTestCase struct { + configStr string + expectedError config.AnyError + message string +} + +var serialDeviceTestcases = []configRetainTestCase{ + // check device validation without retain flag + { + configStr: ` + [[broker."sango/1"]] + host = "localhost" + port = 1883 + + [device."hi"] + type = "serial" + broker = "sango" + serial = "/dev/tty" + baud = 9600 + qos = 0 +`, + expectedError: nil, + message: "Retain flag could not be omitted. Shall be optional."}, + // check device validation with retain flag + { + configStr: ` + [[broker."sango/1"]] + host = "localhost" + port = 1883 + + [device."hi"] + type = "serial" + broker = "sango" + serial = "/dev/tty" + baud = 9600 + qos = 0 + retain = true +`, + expectedError: nil, + message: "Retain flag could not be set."}, + // check device validation with retain flag is false + { + configStr: ` + [[broker."sango/1"]] + host = "localhost" + port = 1883 + + [device."hi"] + type = "serial" + broker = "sango" + serial = "/dev/tty" + baud = 9600 + qos = 0 + retain = false +`, + expectedError: nil, + message: "Retain flag could not be un-set."}, +} + +var dummyDeviceTestcases = []configRetainTestCase{ + // check device validation without retain flag + { + configStr: ` + [[broker."sango/1"]] + host = "localhost" + port = 1883 + + [device."hi"] + type = "dummy" + broker = "sango" + qos = 0 + interval = 10 + payload = "Hello world." +`, + expectedError: nil, + message: "Retain flag could not be omitted. Shall be optional."}, + // check device validation with retain flag + { + configStr: ` + [[broker."sango/1"]] + host = "localhost" + port = 1883 + + [device."hi"] + type = "dummy" + broker = "sango" + qos = 0 + retain = true + interval = 10 + payload = "Hello world." +`, + expectedError: nil, + message: "Retain flag could not be set."}, + // check device validation with retain flag is false + { + configStr: ` + [[broker."sango/1"]] + host = "localhost" + port = 1883 + + [device."hi"] + type = "dummy" + broker = "sango" + qos = 0 + retain = false + interval = 10 + payload = "Hello world." +`, + expectedError: nil, + message: "Retain flag could not be un-set."}, +} + +// generalConfigRetainSerialDeviceTest checks retain function with serial device +func generalConfigRetainSerialDeviceTest(test configRetainTestCase, t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfigByte([]byte(test.configStr)) + assert.Nil(err) + + brokers, err := broker.NewBrokers(conf, make(chan message.Message)) + assert.Nil(err) + + devices, _, err := device.NewDevices(conf, brokers) + assert.Nil(err) + assert.Equal(1, len(devices)) +} + +// generalConfigRetainDummyDeviceTest checks retain function with dummy device +func generalConfigRetainDummyDeviceTest(test configRetainTestCase, t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfigByte([]byte(test.configStr)) + assert.Nil(err) + + brokers, err := broker.NewBrokers(conf, make(chan message.Message)) + assert.Nil(err) + + dummy, err := device.NewDummyDevice(conf.Sections[1], brokers, device.NewDeviceChannel()) + if test.expectedError == nil { + assert.Nil(err) + assert.NotNil(dummy) + } else { + assert.NotNil(err) + } +} + +// TestConfigRetainDeviceAll tests a serial device using test code +func TestConfigRetainDeviceAll(t *testing.T) { + i := 0 + for _, testcase := range serialDeviceTestcases { + generalConfigRetainSerialDeviceTest(testcase, t) + i++ + } +} + +// TestConfigRetainDeviceAll tests a dummy device using test code +func TestConfigRetainDummyDeviceAll(t *testing.T) { + for _, testcase := range dummyDeviceTestcases { + generalConfigRetainDummyDeviceTest(testcase, t) + } +} diff -Nru fuji-0.3.0/tests/toml_test.go fuji-1.0.2/tests/toml_test.go --- fuji-0.3.0/tests/toml_test.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/toml_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,81 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" + "github.com/shiguredo/fuji/device" + "github.com/shiguredo/fuji/gateway" + "github.com/shiguredo/fuji/message" +) + +func TestLoadConfig(t *testing.T) { + assert := assert.New(t) + + _, err := config.LoadConfig("testing_conf.toml") + assert.Nil(err) +} + +func TestNewGateway(t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfig("testing_conf.toml") + assert.Nil(err) + gw, err := gateway.NewGateway(conf) + assert.Nil(err) + assert.Equal("ham", gw.Name) +} + +func TestNewBrokers(t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfig("testing_conf.toml") + assert.Nil(err) + brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) + assert.Nil(err) + assert.Equal(3, len(brokerList)) +} + +func TestNewSerialDevices(t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfig("testing_conf.toml") + brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) + assert.Nil(err) + deviceList, _, err := device.NewDevices(conf, brokerList) + assert.Nil(err) + assert.Equal(3, len(deviceList)) +} + +func TestNewDummyDevice(t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfig("testing_conf.toml") + brokerList, err := broker.NewBrokers(conf, make(chan message.Message)) + assert.Nil(err) + + section := config.SearchDeviceType(&conf.Sections, "dummy") + assert.NotNil(section) + + dummy, err := device.NewDummyDevice(*section, brokerList, device.NewDeviceChannel()) + assert.Nil(err) + assert.Equal("dummy", dummy.DeviceType()) + assert.Equal(2, int(dummy.QoS)) +} diff -Nru fuji-0.3.0/tests/toml_will_test.go fuji-1.0.2/tests/toml_will_test.go --- fuji-0.3.0/tests/toml_will_test.go 1970-01-01 00:00:00.000000000 +0000 +++ fuji-1.0.2/tests/toml_will_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -0,0 +1,116 @@ +// Copyright 2015-2016 Shiguredo Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" + "github.com/shiguredo/fuji/message" +) + +type configWillTestCase struct { + configStr string // testcase config file + expectedError config.AnyError // expected error status + message string // message when failed +} + +var testcases = []configWillTestCase{ + // tests broker validation without will_message + { + configStr: ` + [[broker."sango/1"]] + + host = "localhost" + port = 1883 +`, + expectedError: nil, + message: "WillMessage could not be omitted. Shall be optional."}, + // tests broker validation with will_message + { + configStr: ` + [[broker."sango/1"]] + + host = "localhost" + port = 1883 + will_message = "Hello world." +`, + expectedError: nil, + message: "WillMessage could not be defined."}, + // tests broker validation with empty will_message + { + configStr: ` + [[broker."sango/1"]] + + host = "localhost" + port = 1883 + will_message = "" +`, + expectedError: nil, + message: "Empty WillMessage could not be defined."}, + // tests multiple broker validation with only one will_message + { + configStr: ` + [[broker."sango/1"]] + + host = "localhost" + port = 1883 + + [[broker."sango/2"]] + + host = "192.168.1.1 " + port = 1883 + will_message = "Hello world." +`, + expectedError: nil, + message: "WillMessage could not be defined for one of two."}, + // tests multiple broker validation with both will_message + { + configStr: ` + [[broker."sango/1"]] + + host = "localhost" + port = 1883 + will_message = "Change the world." + + [[broker."sango/2"]] + + host = "192.168.1.1" + port = 1883 + will_message = "Hello world." +`, + expectedError: nil, + message: "WillMessage could not be defined for both of two."}, +} + +func generalConfigWillTest(test configWillTestCase, t *testing.T) { + assert := assert.New(t) + + conf, err := config.LoadConfigByte([]byte(test.configStr)) + assert.Nil(err) + + brokers, err := broker.NewBrokers(conf, make(chan message.Message)) + assert.Nil(err) + assert.NotEqual(0, len(brokers)) +} + +func TestConfigWillAll(t *testing.T) { + for _, testcase := range testcases { + generalConfigWillTest(testcase, t) + } +} diff -Nru fuji-0.3.0/tests/will_test.go fuji-1.0.2/tests/will_test.go --- fuji-0.3.0/tests/will_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/tests/will_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,18 +16,23 @@ import ( "fmt" + "os" + "os/exec" + "path/filepath" "testing" "time" - MQTT "git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git" + MQTT "github.com/eclipse/paho.mqtt.golang" "github.com/stretchr/testify/assert" "github.com/shiguredo/fuji" "github.com/shiguredo/fuji/broker" + "github.com/shiguredo/fuji/config" "github.com/shiguredo/fuji/gateway" - "github.com/shiguredo/fuji/inidef" ) +var tmpTomlName = ".tmp.toml" + // TestWillJustPublish tests // 1. connect localhost broker with will message // 2. send data from a dummy device @@ -35,21 +40,21 @@ func TestWillJustPublish(t *testing.T) { assert := assert.New(t) - iniStr := ` + configStr := ` [gateway] - name = willjustpublishham - [broker "local/1"] - host = localhost + name = "willjustpublishham" + [[broker."local/1"]] + host = "localhost" port = 1883 - will_message = no letter is good letter. - [device "dora/dummy"] - broker = local + will_message = "no letter is good letter." + [device."dora"] + type = "dummy" + broker = "local" qos = 0 interval = 10 - payload = Hello will just publish world. - type = EnOcean + payload = "Hello will just publish world." ` - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) assert.Nil(err) commandChannel := make(chan string) go fuji.StartByFileWithChannel(conf, commandChannel) @@ -58,6 +63,60 @@ // fuji.Stop() } +// TestWillWithPrefixSubscribePublishClose +// 1. connect subscriber and publisher to localhost broker with will message with prefixed topic +// 2. send data from a dummy device +// 3. force disconnect +// 4. check subscriber does not receives will message immediately +func TestWillWithPrefixSubscribePublishClose(t *testing.T) { + assert := assert.New(t) + + configStr := ` + [gateway] + name = "testprefixwill" + [[broker."local/1"]] + host = "localhost" + port = 1883 + will_message = "no letter is good letter." + topic_prefix = "prefix" + [device."dora"] + type = "dummy" + broker = "local" + qos = 0 + interval = 10 + payload = "Hello will with prefix." +` + expectedWill := true + ok := genericWillTestDriver(t, configStr, "prefix/testprefixwill/will", []byte("no letter is good letter."), expectedWill) + assert.True(ok, "Failed to receive Will with prefix message") +} + +// TestNoWillSubscribePublishClose +// 1. connect subscriber and publisher to localhost broker without will message +// 2. send data from a dummy device +// 3. force disconnect +// 4. check subscriber does not receives will message immediately +func TestNoWillSubscribePublishClose(t *testing.T) { + assert := assert.New(t) + + configStr := ` + [gateway] + name = "testnowillafterclose" + [[broker."local/1"]] + host = "localhost" + port = 1883 + [device."dora"] + type = "dummy" + broker = "local" + qos = 0 + interval = 10 + payload = "Hello will just publish world." +` + expectedWill := false + ok := genericWillTestDriver(t, configStr, "/testnowillafterclose/will", []byte(""), expectedWill) + assert.False(ok, "Failed to receive Will message") +} + // TestWillSubscribePublishClose // 1. connect subscriber and publisher to localhost broker with will message // 2. send data from a dummy device @@ -66,21 +125,22 @@ func TestWillSubscribePublishClose(t *testing.T) { assert := assert.New(t) - iniStr := ` + configStr := ` [gateway] - name = testwillafterclose - [broker "local/1"] - host = localhost + name = "testwillafterclose" + [[broker."local/1"]] + host = "localhost" port = 1883 - will_message = good letter is no letter. - [device "dora/dummy"] - broker = local + will_message = "good letter is no letter." + [device."dora"] + type = "dummy" + broker = "local" qos = 0 interval = 10 - payload = Hello will just publish world. - type = EnOcean + payload = "Hello will just publish world." ` - ok := genericWillTestDriver(t, iniStr, "/testwillafterclose/will", []byte("good letter is no letter.")) + expectedWill := true + ok := genericWillTestDriver(t, configStr, "/testwillafterclose/will", []byte("good letter is no letter."), expectedWill) assert.True(ok, "Failed to receive Will message") } @@ -90,47 +150,83 @@ // 3. force disconnect // 4. check subscriber receives will message func TestWillSubscribePublishCloseEmpty(t *testing.T) { - iniStr := ` + configStr := ` [gateway] - name = testwillaftercloseemptywill - [broker "local/1"] - host = localhost + name = "testwillaftercloseemptywill" + [[broker."local/1"]] + host = "localhost" port = 1883 - will_message = - [device "dora/dummy"] - broker = local + will_message = "" + [device."dora"] + type = "dummy" + broker = "local" qos = 0 interval = 10 - payload = Hello will just publish world. - type = EnOcean + payload = "Hello will just publish world." ` - ok := genericWillTestDriver(t, iniStr, "/testwillaftercloseemptywill/will", []byte{}) + expectedWill := true + ok := genericWillTestDriver(t, configStr, "/testwillaftercloseemptywill/will", []byte{}, expectedWill) if !ok { t.Error("Failed to receive Empty Will message") } } func TestWillSubscribePublishBinaryWill(t *testing.T) { - iniStr := ` + configStr := ` [gateway] - name = binary - [broker "local/1"] - host = localhost + name = "binary" + [[broker."local/1"]] + host = "localhost" port = 1883 - will_message = \x01\x02 - [device "dora/dummy"] - broker = local + will_message = "\\x01\\x02" + [device."dora"] + type = "dummy" + broker = "local" qos = 0 interval = 10 - payload = Hello will just publish world. - type = EnOcean + payload = "Hello will just publish world." +` + expectedWill := true + ok := genericWillTestDriver(t, configStr, "/binary/will", []byte{1, 2}, expectedWill) + if !ok { + t.Error("Failed to receive Empty Will message") + } +} + +func TestWillSubscribePublishWillWithWillTopic(t *testing.T) { + configStr := ` + [gateway] + name = "with" + [[broker."local/1"]] + host = "localhost" + port = 1883 + will_message = "msg" + will_topic = "willtopic" ` - ok := genericWillTestDriver(t, iniStr, "/binary/will", []byte{1, 2}) + expectedWill := true + ok := genericWillTestDriver(t, configStr, "/willtopic", []byte("msg"), expectedWill) if !ok { t.Error("Failed to receive Empty Will message") } } +func TestWillSubscribePublishWillWithNestedWillTopic(t *testing.T) { + configStr := ` + [gateway] + name = "withnested" + [[broker."local/1"]] + host = "localhost" + port = 1883 + will_message = "msg" + will_topic = "willtopic/nested" +` + expectedWill := true + ok := genericWillTestDriver(t, configStr, "/willtopic/nested", []byte("msg"), expectedWill) + if !ok { + t.Error("Failed to receive nested willtopic Will message") + } +} + // genericWillTestDriver // 1. read config string // 2. connect subscriber and publisher to localhost broker with will message @@ -138,48 +234,85 @@ // 4. force disconnect // 5. check subscriber receives will message -func genericWillTestDriver(t *testing.T, iniStr string, expectedTopic string, expectedPayload []byte) (ok bool) { +func genericWillTestDriver(t *testing.T, configStr string, expectedTopic string, expectedPayload []byte, expectedWill bool) (ok bool) { assert := assert.New(t) - conf, err := inidef.LoadConfigByte([]byte(iniStr)) + conf, err := config.LoadConfigByte([]byte(configStr)) assert.Nil(err) - commandChannel := make(chan string) - go fuji.StartByFileWithChannel(conf, commandChannel) + // write config string to temporal file + f, err := os.Create(tmpTomlName) + if err != nil { + t.Error(err) + } + _, err = f.WriteString(configStr) + if err != nil { + t.Error(err) + } + f.Sync() + + // execute fuji as external process + fujiPath, err := filepath.Abs("../fuji") + if err != nil { + t.Error("file path not found") + } + cmd := exec.Command(fujiPath, "-c", tmpTomlName) + err = cmd.Start() + if err != nil { + t.Error(err) + } + + // subscriber setup gw, err := gateway.NewGateway(conf) assert.Nil(err) brokers, err := broker.NewBrokers(conf, gw.BrokerChan) assert.Nil(err) - go func() { - time.Sleep(1 * time.Second) + subscriberChannel, err := setupWillSubscriber(gw, brokers[0], t) + if err != config.Error("") { + t.Error(err) + } - subscriberChannel, err := setupWillSubscriber(gw, brokers[0]) - if err != inidef.Error("") { - t.Error(err) - } + fin := make(chan bool) - time.Sleep(1 * time.Second) + go func() { + // check will message + willCame := true + select { + case willMsg := <-subscriberChannel: + if expectedWill { + assert.Equal(expectedTopic, willMsg.Topic()) + assert.Equal(expectedPayload, willMsg.Payload()) + assert.Equal(byte(0), willMsg.Qos()) + } else { + assert.Equal("NO will message received within 1 sec", "unexpected will message received.") + } + case <-time.After(time.Second * 2): + if expectedWill { + assert.Equal("will message received within 1 sec", "not completed") + } + willCame = false + } + fin <- willCame + }() - // kill publisher - brokers[0].FourceClose() - fmt.Println("broker killed for getting will message") + // wait for startup of external command process + time.Sleep(time.Second * 1) - // check will message - willMsg := <-subscriberChannel + // kill publisher + err = cmd.Process.Kill() + if err != nil { + t.Error(err) + } + t.Log("broker killed for getting will message") - assert.Equal(expectedTopic, willMsg.Topic()) - assert.Equal(expectedPayload, willMsg.Payload()) - assert.Equal(byte(0), willMsg.Qos()) - }() - time.Sleep(3 * time.Second) - ok = true + ok = <-fin return ok } // setupWillSubscriber start subscriber process and returnes a channel witch can receive will message. -func setupWillSubscriber(gw *gateway.Gateway, broker *broker.Broker) (chan MQTT.Message, inidef.Error) { +func setupWillSubscriber(gw *gateway.Gateway, broker *broker.Broker, t *testing.T) (chan MQTT.Message, config.Error) { // Setup MQTT pub/sub client to confirm published content. // messageOutputChannel := make(chan MQTT.Message) @@ -192,21 +325,21 @@ opts.SetDefaultPublishHandler(func(client *MQTT.Client, msg MQTT.Message) { messageOutputChannel <- msg }) + willQoS := 0 + willTopic := broker.WillTopic + t.Logf("expected will_topic: %s", willTopic) client := MQTT.NewClient(opts) if client == nil { - return nil, inidef.Error("NewClient failed") + return nil, config.Error("NewClient failed") } if token := client.Connect(); token.Wait() && token.Error() != nil { - return nil, inidef.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) + return nil, config.Error(fmt.Sprintf("NewClient Start failed %q", token.Error())) } - qos := 0 - // assume topicPrefix == "" - willTopic := fmt.Sprintf("/%s/will", gw.Name) - client.Subscribe(willTopic, byte(qos), func(client *MQTT.Client, msg MQTT.Message) { + client.Subscribe(willTopic, byte(willQoS), func(client *MQTT.Client, msg MQTT.Message) { messageOutputChannel <- msg }) - return messageOutputChannel, inidef.Error("") + return messageOutputChannel, config.Error("") } diff -Nru fuji-0.3.0/utils/parser.go fuji-1.0.2/utils/parser.go --- fuji-0.3.0/utils/parser.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/utils/parser.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff -Nru fuji-0.3.0/utils/parser_test.go fuji-1.0.2/utils/parser_test.go --- fuji-0.3.0/utils/parser_test.go 2015-10-07 05:51:57.000000000 +0000 +++ fuji-1.0.2/utils/parser_test.go 2016-03-23 04:35:15.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright 2015 Shiguredo Inc. +// Copyright 2015-2016 Shiguredo Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.