- 实现 MIoT 客户端核心功能(MQTT 连接、设备管理、属性读写) - 支持云端 API 调用与局域网设备发现(mDNS) - 集成国际化(i18n)多语言支持 - 添加 MIoT 设备规约解析器(spec_parser) - 包含单元测试与使用示例
191 lines
4.7 KiB
Go
191 lines
4.7 KiB
Go
// Package miot provides white-box tests for miot_cloud.go cloud API client.
|
|
package miot
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestToFloat64(t *testing.T) {
|
|
tests := []struct {
|
|
input interface{}
|
|
want float64
|
|
}{
|
|
{float64(3.14), 3.14},
|
|
{int(5), 5.0},
|
|
{int64(10), 10.0},
|
|
{"123", 123.0},
|
|
{nil, 0.0},
|
|
{true, 0.0},
|
|
}
|
|
for _, tt := range tests {
|
|
got := toFloat64(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("toFloat64(%v) = %f, want %f", tt.input, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestToSlice(t *testing.T) {
|
|
if s := toSlice(nil); s != nil {
|
|
t.Errorf("toSlice(nil) = %v, want nil", s)
|
|
}
|
|
if s := toSlice([]interface{}{"a", "b"}); len(s) != 2 {
|
|
t.Errorf("toSlice len = %d, want 2", len(s))
|
|
}
|
|
if s := toSlice("not_a_slice"); s != nil {
|
|
t.Errorf("toSlice(string) = %v, want nil", s)
|
|
}
|
|
}
|
|
|
|
func TestToStringSlice(t *testing.T) {
|
|
s := toStringSlice([]string{"a", "b", "c"})
|
|
if len(s) != 3 || s[0] != "a" {
|
|
t.Errorf("toStringSlice([]string) = %v", s)
|
|
}
|
|
s = toStringSlice([]interface{}{"x", "y"})
|
|
if len(s) != 2 || s[1] != "y" {
|
|
t.Errorf("toStringSlice([]interface{}) = %v", s)
|
|
}
|
|
s = toStringSlice([]interface{}{"str", 42})
|
|
if s[1] != "42" {
|
|
t.Errorf("toStringSlice with int = %v, want '42'", s)
|
|
}
|
|
s = toStringSlice(nil)
|
|
if s != nil {
|
|
t.Errorf("toStringSlice(nil) should be nil, got %v", s)
|
|
}
|
|
}
|
|
|
|
func TestIsUnsupportedModel(t *testing.T) {
|
|
if !isUnsupportedModel("chuangmi.ir.v2") {
|
|
t.Error("chuangmi.ir.v2 should be unsupported")
|
|
}
|
|
if isUnsupportedModel("lumi.plug.v1") {
|
|
t.Error("lumi.plug.v1 should be supported")
|
|
}
|
|
if isUnsupportedModel("") {
|
|
t.Error("empty string should be supported")
|
|
}
|
|
}
|
|
|
|
func TestContainsString(t *testing.T) {
|
|
slice := []string{"a", "b", "c"}
|
|
if !containsString(slice, "b") {
|
|
t.Error("should contain 'b'")
|
|
}
|
|
if containsString(slice, "z") {
|
|
t.Error("should not contain 'z'")
|
|
}
|
|
if containsString(nil, "a") {
|
|
t.Error("nil slice should not contain anything")
|
|
}
|
|
}
|
|
|
|
func TestNewMIoTHttpClient_Basic(t *testing.T) {
|
|
client, err := NewMIoTHttpClient("cn", "client_id_123", "access_token_abc")
|
|
if err != nil {
|
|
t.Fatalf("NewMIoTHttpClient failed: %v", err)
|
|
}
|
|
if client == nil {
|
|
t.Fatal("client should not be nil")
|
|
}
|
|
client.Close()
|
|
}
|
|
|
|
func TestNewMIoTHttpClient_NonCN(t *testing.T) {
|
|
client, err := NewMIoTHttpClient("us", "id", "token")
|
|
if err != nil {
|
|
t.Fatalf("NewMIoTHttpClient for us failed: %v", err)
|
|
}
|
|
client.Close()
|
|
}
|
|
|
|
func TestNewMIoTOauthClient_Basic(t *testing.T) {
|
|
oa := NewMIoTOauthClient("2882303761520251711", "http://localhost/callback", "cn", "test-uuid")
|
|
if oa == nil {
|
|
t.Fatal("NewMIoTOauthClient returned nil")
|
|
}
|
|
s := oa.State()
|
|
if s == "" {
|
|
t.Error("State should not be empty")
|
|
}
|
|
oa.Close()
|
|
}
|
|
|
|
func TestGenAuthURL(t *testing.T) {
|
|
oa := NewMIoTOauthClient("2882303761520251711", "http://localhost/callback", "cn", "test-uuid")
|
|
defer oa.Close()
|
|
|
|
url := oa.GenAuthURL("", "", nil, false)
|
|
if url == "" {
|
|
t.Error("GenAuthURL returned empty string")
|
|
}
|
|
|
|
url2 := oa.GenAuthURL("http://custom/callback", "mystate", []string{"scope1", "scope2"}, true)
|
|
if url2 == "" {
|
|
t.Error("GenAuthURL with params returned empty string")
|
|
}
|
|
}
|
|
|
|
func TestUpdateHTTPHeader_CN(t *testing.T) {
|
|
client, err := NewMIoTHttpClient("cn", "id1", "tok1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer client.Close()
|
|
client.UpdateHTTPHeader("cn", "new_id", "new_token")
|
|
}
|
|
|
|
func TestUpdateHTTPHeader_NonCN(t *testing.T) {
|
|
client, err := NewMIoTHttpClient("us", "id1", "tok1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer client.Close()
|
|
client.UpdateHTTPHeader("de", "id2", "tok2")
|
|
}
|
|
|
|
func TestMihomeAPIGet_Success(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
t.Errorf("expected GET, got %s", r.Method)
|
|
}
|
|
resp := map[string]interface{}{"code": float64(0), "message": "ok", "result": map[string]interface{}{"data": "test"}}
|
|
json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
defer server.Close()
|
|
_ = server
|
|
}
|
|
|
|
func TestPropParam_Struct(t *testing.T) {
|
|
p := PropParam{DID: "did1", Siid: 2, Piid: 1, Value: "on"}
|
|
if p.DID != "did1" || p.Siid != 2 || p.Piid != 1 {
|
|
t.Error("PropParam fields wrong")
|
|
}
|
|
}
|
|
|
|
func TestPropResult_Struct(t *testing.T) {
|
|
r := PropResult{DID: "did1", Siid: 2, Piid: 1, Code: 0, Value: "ok"}
|
|
if r.Code != 0 {
|
|
t.Errorf("PropResult Code = %d, want 0", r.Code)
|
|
}
|
|
}
|
|
|
|
func TestMIoTHttpClient_Close(t *testing.T) {
|
|
client, err := NewMIoTHttpClient("cn", "id", "token")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client.Close()
|
|
client.Close()
|
|
}
|
|
|
|
func TestTokenExpiresTSRatio(t *testing.T) {
|
|
if TokenExpiresTSRatio <= 0 || TokenExpiresTSRatio >= 1.0 {
|
|
t.Errorf("TokenExpiresTSRatio = %f, should be between 0 and 1", TokenExpiresTSRatio)
|
|
}
|
|
}
|