package transpile import ( "bytes" "strings" "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) // Trim removes all the whitespaces and returns a new string. func Trim(s string) string { s = strings.Replace(s, " ", "", -1) s = strings.Replace(s, "\n", "", -1) s = strings.Replace(s, "\r", "", -1) s = strings.Replace(s, "\t", "", -1) return s } // Validate the content of a given source with an expected outcome by using a string compare. // The defaultService will be started and used to transform the source into an Arduino sketch format. func Validate(source, expected string, t *testing.T) { RegisterTestingT(t) var in, out bytes.Buffer in.WriteString(source) service := NewService(&in, &out) err := service.Start() got := out.String() tgot, texpected := Trim(got), Trim(expected) ExpectWithOffset(1, err).NotTo(HaveOccurred()) ExpectWithOffset(1, tgot).To(Be(texpected)) } func Compare(source, expected string) { var in, out bytes.Buffer in.WriteString(source) service := NewService(&in, &out) err := service.Start() got := out.String() tgot, texpected := Trim(got), Trim(expected) ExpectWithOffset(1, err).NotTo(HaveOccurred()) ExpectWithOffset(1, tgot).To(Be(texpected)) } func Test_Empty_Package(t *testing.T) { source := `package test` expected := `void loop(){} void setup() {} ` Validate(source, expected, t) } func Test_Function_Declaration(t *testing.T) { source := `package test func foo() {} func bar() {} ` expected := `void foo(){} void bar() {} ` Validate(source, expected, t) } func Test_Function_Declaration_With_Args(t *testing.T) { source := `package test func foo(x int) {} func bar(y int) {} ` expected := `void foo(int x){} void bar(int y) {} ` Validate(source, expected, t) } func Test_Const_String_Declaration(t *testing.T) { source := `package test const foo string = "bar" ` expected := ` const char* foo = "bar"; ` Validate(source, expected, t) } func Test_Var_String_Declaration(t *testing.T) { source := `package test var client wifi.Client ` expected := ` WiFiClient client; ` Validate(source, expected, t) } func Test_Function_With_Const_String_Declaration(t *testing.T) { source := `package test func foo() { const foo string = "bar" } ` expected := ` void foo() { const char* foo = "bar"; } ` Validate(source, expected, t) } func Test_Function_With_Var_String_Declaration(t *testing.T) { source := `package test func foo() { var foo string = "bar" } ` expected := ` void foo() { char* foo = "bar"; } ` Validate(source, expected, t) } func Test_Function_With_Function_Call(t *testing.T) { source := `package test func foo() { bar() } ` expected := ` void foo() { bar(); } ` Validate(source, expected, t) } func Test_Function_With_Function_Call_With_Args(t *testing.T) { source := `package test func foo() { bar(1,2,3) } ` expected := ` void foo() { bar(1,2,3); } ` Validate(source, expected, t) } func Test_Function_With_Function_Call_With_String(t *testing.T) { source := `package test func foo() { bar("foo") } ` expected := ` void foo() { bar("foo"); } ` Validate(source, expected, t) } func Test_Function_With_Package_Function_Call(t *testing.T) { source := `package test func foo() { foo.Bar(1,"2") } ` expected := ` void foo() { foo.Bar(1,"2"); } ` Validate(source, expected, t) } func Test_Function_With_Assignments(t *testing.T) { source := `package test func foo() { x = 1 y = 2 z = x + y } ` expected := ` void foo() { x = 1; y = 2; z = x + y; } ` Validate(source, expected, t) } func Test_Function_With_Package_Selector_Assignments(t *testing.T) { source := `package test func foo() { x = bar() y = pkg.Bar() z = x + y } ` expected := ` void foo() { x = bar(); y = pkg.Bar(); z = x + y; } ` Validate(source, expected, t) } func Test_Function_Ident_Mapping(t *testing.T) { source := `package test func foo() { serial.Begin() } ` expected := ` void foo() { Serial.begin(); } ` Validate(source, expected, t) } func Test_Function_With_Ident_Param(t *testing.T) { source := `package test func foo() { foo.Bar(1,"2",digital.Low) } ` expected := ` void foo() { foo.Bar(1,"2",LOW); } ` Validate(source, expected, t) } func Test_Function_With_Function_Param(t *testing.T) { source := `package test func foo() { serial.Println(wifi.LocalIP()) } ` expected := ` void foo() { Serial.println(WiFi.localIP()); } ` Validate(source, expected, t) } func Test_Package_Import(t *testing.T) { source := `package test import "github.com/andygeiss/esp32-mqtt/api/controller" import "github.com/andygeiss/esp32-mqtt/api/controller/serial" import "github.com/andygeiss/esp32/api/controller/timer" import wifi "github.com/andygeiss/esp32/api/controller/wifi" ` expected := ` #include ` Validate(source, expected, t) } func Test_Package_Import_But_Ignore_Controller(t *testing.T) { source := `package test import controller "github.com/andygeiss/esp32-controller" import "github.com/andygeiss/esp32-mqtt/api/controller/serial" import "github.com/andygeiss/esp32/api/controller/timer" import wifi "github.com/andygeiss/esp32/api/controller/wifi" ` expected := ` #include ` Validate(source, expected, t) } func Test_IfStmt_With_Condition_BasicLit_And_BasicLit(t *testing.T) { source := `package test func Setup() {} func Loop() { if 1 == 1 { serial.Println("1") } } ` expected := ` void setup() {} void loop() { if (1 == 1) { Serial.println("1"); } } ` Validate(source, expected, t) } func Test_IfStmt_With_Condition_Ident_And_BasicLit(t *testing.T) { source := `package test func Setup() {} func Loop() { if x == 1 { serial.Println("1") } } ` expected := ` void setup() {} void loop() { if (x == 1) { Serial.println("1"); } } ` Validate(source, expected, t) } func Test_IfStmt_With_Condition_CallExpr_And_BasicLit(t *testing.T) { source := `package test func Setup() {} func Loop() { if x() == 1 { serial.Println("1") } } ` expected := ` void setup() {} void loop() { if (x() == 1) { Serial.println("1"); } } ` Validate(source, expected, t) } func Test_IfStmt_With_Condition_Const_And_BasicLit(t *testing.T) { source := `package test const maxX = 1 func Setup() {} func Loop() { if x == maxX { serial.Println("1") } } ` expected := ` const maxX = 1; void setup() {} void loop() { if (x == maxX) { Serial.println("1"); } } ` Validate(source, expected, t) } func Test_IfStmt_With_Else(t *testing.T) { source := `package test const maxX = 1 func Setup() {} func Loop() { if x == maxX { serial.Println("1") } else { serial.Println("2") } } ` expected := ` const maxX = 1; void setup() {} void loop() { if (x == maxX) { Serial.println("1"); } else { Serial.println("2"); } } ` Validate(source, expected, t) } func Test_SwitchStmt_With_Ident_And_BasicLit(t *testing.T) { source := `package test func Setup() {} func Loop() { switch x { case 1: serial.Println("1") } } ` expected := ` void setup() {} void loop() { switch (x) { case 1: Serial.println("1"); } } ` Validate(source, expected, t) } func Test_SwitchStmt_With_Break(t *testing.T) { source := `package test func Setup() {} func Loop() { switch x { case 1: serial.Println("1") break case 2: serial.Println("1") } } ` expected := ` void setup() {} void loop() { switch (x) { case 1: Serial.println("1"); break; case 2: Serial.println("1"); } } ` Validate(source, expected, t) } func Test_ForLoop_WithoutInit_And_Post_Transpiles_To_While(t *testing.T) { source := `package test import wifi "github.com/andygeiss/esp32/api/controller/wifi" func Setup() { serial.Begin(serial.BaudRate115200) wifi.BeginEncrypted("SSID", "PASS") for wifi.Status() != wifi.StatusConnected { serial.Println("Connecting ...") } serial.Println("Connected!") return nil } func Loop() {} ` expected := ` #include void setup() { Serial.begin(115200); WiFi.begin("SSID","PASS"); while(WiFi.status()!=WL_CONNECTED){ Serial.println("Connecting..."); } Serial.println("Connected!"); } void loop() {} ` Validate(source, expected, t) } func Test_WiFiWebClient(t *testing.T) { source := `package test import wifi "github.com/andygeiss/esp32/api/controller/wifi" var client wifi.Client func Setup() {} func Loop() { serial.Print("Connecting to ") serial.Println(host) serial.Print(" ...") if (client.Connect(host, 443) == true) { serial.Println(" Connected!") } else { serial.Println(" Failed!") } } ` expected := `#include WiFiClient client; voidsetup(){} voidloop(){ Serial.print("Connecting to"); Serial.println(host); Serial.print(" ..."); if(client.connect(host, 443) == true){ Serial.println(" Connected!"); } else { Serial.println(" Failed!"); } }` Validate(source, expected, t) } func TestUtils(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Go Translator") } func NDescribe(s string, i func()) int { return 0 } func NIt(s string, i func()) int { return 0 } func NIt_async(s string, i func(done Done), timeout float64) int { return 0 } var Be = Equal func BeCalled(called bool) { ExpectWithOffset(1, called).To(BeTrue()) } func NoErr(err error) { ExpectWithOffset(1, err).NotTo(HaveOccurred()) } var Ok = NoErr func ErrBe(err error, must error) { if must != nil { Ω(err).To(Be(must)) } else { Ω(err).To(BeNil()) } } func ToBeTrue(arg bool) { Ω(arg).To(BeTrue()) } var _ = Describe("Go Translator", func() { Describe("Arduino", func() { It("Maps constants", func() { source := `package test var analogInPin int = arduino.A0 func Setup() {} func Loop() {} ` expected := ` int analogInPin = A0; void setup() {} void loop() {} ` Compare(source, expected) }) }) })