Integration test (#13)

diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
new file mode 100644
index 0000000..88052db
--- /dev/null
+++ b/.github/workflows/e2e.yml
@@ -0,0 +1,32 @@
+name: E2E Tests
+
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+
+  build:
+    name: e2e test
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-latest]
+    steps:
+
+    - name: Check out code into the Go module directory
+      uses: actions/checkout@v2
+
+    - name: Cache local Maven repository
+      uses: actions/cache@v2
+      with:
+        path: ~/.m2/repository
+        key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+        restore-keys: |
+          ${{ runner.os }}-maven-
+
+    - name: Integration test
+      run: |
+        make e2e_test e2e_test_clean
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index c7f413c..b2dc938 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -32,4 +32,4 @@
       run: go build -v ./...
 
     - name: Test
-      run: go test -v ./...
+      run: make test
diff --git a/Makefile b/Makefile
index cf0469d..942038e 100644
--- a/Makefile
+++ b/Makefile
@@ -22,4 +22,17 @@
 	@thrift -out . -gen go rpc.thrift
 	@rm -rf rpc/t_s_i_service-remote rpc.thrift
 
-.PHONY: generate all
+.PHONY: generate all test e2e_test e2e_test_clean
+
+test:
+	go test -v ./client/...
+
+e2e_test:
+	sh -c "cd /tmp/ && rm -rf iotdb && git clone https://github.com/apache/iotdb.git && cd iotdb && mvn -Dmaven.test.skip=true package -am -pl server"
+	mkdir -p docker-context/iotdb
+	unzip -o -q /tmp/iotdb/server/target/iotdb-server-*.zip -d docker-context/iotdb
+	docker-compose -f test/e2e/docker-compose.yml up --build --abort-on-container-exit --remove-orphans
+
+e2e_test_clean:
+	rm -rf /tmp/iotdb docker-context
+	docker-compose -f test/e2e/docker-compose.yml down
diff --git a/example/session_example.go b/example/session_example.go
index bb87841..baa3328 100644
--- a/example/session_example.go
+++ b/example/session_example.go
@@ -21,6 +21,7 @@
 
 import (
 	"errors"
+	"flag"
 	"fmt"
 	"log"
 	"math/rand"
@@ -30,14 +31,25 @@
 	"github.com/apache/iotdb-client-go/rpc"
 )
 
+var (
+	host     string
+	port     string
+	user     string
+	password string
+)
 var session *client.Session
 
 func main() {
+	flag.StringVar(&host, "host", "127.0.0.1", "--host=192.168.1.100")
+	flag.StringVar(&port, "port", "6667", "--port=6667")
+	flag.StringVar(&user, "user", "root", "--user=root")
+	flag.StringVar(&password, "password", "root", "--password=root")
+	flag.Parse()
 	config := &client.Config{
-		Host:     "127.0.0.1",
-		Port:     "6667",
-		UserName: "root",
-		Password: "root",
+		Host:     host,
+		Port:     port,
+		UserName: user,
+		Password: password,
 	}
 	session = client.NewSession(config)
 	if err := session.Open(false, 0); err != nil {
@@ -95,8 +107,8 @@
 	deleteTimeseries("root.ln.wf02.wt02.s5")
 
 	//0.12.x and newer
-	// insertRecordsOfOneDevice()
-	// deleteTimeseries("root.sg1.dev0.*")
+	insertRecordsOfOneDevice()
+	deleteTimeseries("root.sg1.dev0.*")
 }
 
 func printDevice1(sds *client.SessionDataSet) {
diff --git a/test/e2e/Dockerfile.iotdb-client-go b/test/e2e/Dockerfile.iotdb-client-go
new file mode 100644
index 0000000..6b8c22f
--- /dev/null
+++ b/test/e2e/Dockerfile.iotdb-client-go
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+FROM golang:1.13-alpine
+
+ENV CGO_ENABLED=0
+COPY . /go/src/github.com/apache/iotdb-client-go/
+WORKDIR /go/src/github.com/apache/iotdb-client-go
+CMD [ "go", "test", "-v", "./test/e2e/..." ]
diff --git a/test/e2e/Dockerfile.iotdb-server b/test/e2e/Dockerfile.iotdb-server
new file mode 100644
index 0000000..ed46745
--- /dev/null
+++ b/test/e2e/Dockerfile.iotdb-server
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+FROM openjdk:11-jre-slim
+
+RUN apt update \
+  && apt install -y procps && apt clean
+ADD docker-context /usr/local
+WORKDIR /usr/local/iotdb
+EXPOSE 6667
+CMD [ "/usr/local/iotdb/sbin/start-server.sh" ]
diff --git a/test/e2e/docker-compose.yml b/test/e2e/docker-compose.yml
new file mode 100644
index 0000000..a2cb793
--- /dev/null
+++ b/test/e2e/docker-compose.yml
@@ -0,0 +1,41 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+version: "3.1"
+
+services:
+  iotdb:
+    build:
+      context: ../..
+      dockerfile: test/e2e/Dockerfile.iotdb-server
+    ports:
+      - 6667:6667
+    healthcheck:
+      test: ["CMD", "ls", "/usr/local/iotdb/data"]
+      interval: 3s
+      timeout: 5s
+      retries: 30
+      start_period: 30s
+  iotdb_client_go:
+    build:
+      context: ../..
+      dockerfile: test/e2e/Dockerfile.iotdb-client-go
+    depends_on:
+      iotdb:
+        condition: service_healthy
\ No newline at end of file
diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go
new file mode 100644
index 0000000..753407d
--- /dev/null
+++ b/test/e2e/e2e_test.go
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 e2e
+
+import (
+	"testing"
+	"time"
+
+	"github.com/apache/iotdb-client-go/client"
+	"github.com/apache/iotdb-client-go/rpc"
+	"github.com/stretchr/testify/suite"
+)
+
+type e2eTestSuite struct {
+	suite.Suite
+	session *client.Session
+}
+
+func TestE2ETestSuite(t *testing.T) {
+	suite.Run(t, &e2eTestSuite{})
+}
+
+func (s *e2eTestSuite) SetupSuite() {
+	config := &client.Config{
+		Host:     "iotdb",
+		Port:     "6667",
+		UserName: "root",
+		Password: "root",
+	}
+
+	s.session = client.NewSession(config)
+	err := s.session.Open(false, 0)
+	s.Require().NoError(err)
+}
+
+func (s *e2eTestSuite) TearDownSuite() {
+	s.session.Close()
+}
+
+func (s *e2eTestSuite) SetupTest() {
+	r, err := s.session.SetStorageGroup("root.tsg1")
+	s.checkError(r, err)
+}
+
+func (s *e2eTestSuite) TearDownTest() {
+	r, err := s.session.DeleteStorageGroup("root.tsg1")
+	s.checkError(r, err)
+}
+
+func (s *e2eTestSuite) checkError(status *rpc.TSStatus, err error) {
+	s.Require().NoError(err)
+	if status != nil {
+		s.Require().NoError(client.VerifySuccess(status))
+	}
+}
+
+func (s *e2eTestSuite) Test_CreateTimeseries() {
+	var (
+		path       = "root.tsg1.dev1.status"
+		dataType   = client.FLOAT
+		encoding   = client.PLAIN
+		compressor = client.SNAPPY
+	)
+	s.checkError(s.session.CreateTimeseries(path, dataType, encoding, compressor, nil, nil))
+	ds, err := s.session.ExecuteQueryStatement("show timeseries root.tsg1.dev1.status", 1000)
+
+	assert := s.Require()
+
+	assert.NoError(err)
+	defer ds.Close()
+	assert.True(ds.Next())
+	var timeseries string
+	assert.NoError(ds.Scan(&timeseries))
+	assert.Equal(timeseries, "root.tsg1.dev1.status")
+}
+
+func (s *e2eTestSuite) Test_InsertRecords() {
+	var (
+		deviceId     = []string{"root.tsg1.dev1"}
+		measurements = [][]string{{"status"}}
+		dataTypes    = [][]client.TSDataType{{client.TEXT}}
+		values       = [][]interface{}{{"Working"}}
+		timestamp    = []int64{time.Now().UTC().UnixNano() / 1000000}
+	)
+	s.checkError(s.session.InsertRecords(deviceId, measurements, dataTypes, values, timestamp))
+
+	ds, err := s.session.ExecuteQueryStatement("select status from root.tsg1.dev1", 1000)
+	assert := s.Require()
+	assert.NoError(err)
+	defer ds.Close()
+	assert.True(ds.Next())
+	var status string
+	assert.NoError(ds.Scan(&status))
+	assert.Equal(status, "Working")
+}