From ea7f2e9ecf23b3c219bc88aef76ae5d8a300df36 Mon Sep 17 00:00:00 2001
From: yi-ge-dian <1085266008@qq.com>
Date: Mon, 14 Aug 2023 21:59:47 +0800
Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20test(e2e):=20fiinish=20knative?=
 =?UTF-8?q?=20openfunction=20state?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: yi-ge-dian <1085266008@qq.com>
---
 .github/workflows/e2e.yaml                    |  25 +-
 test/e2e/kind.yaml                            |  20 ++
 .../delete/.env-cmdrc.js                      |  18 ++
 .../delete/Dockerfile.knative.state.delete    |  19 ++
 .../delete/function.js                        |  16 +
 test/e2e/knative-openfunction-state/e2e.yaml  |  90 ++++++
 .../expected.data.yaml                        |   9 +
 .../get/.env-cmdrc.js                         |  18 ++
 .../get/Dockerfile.knative.state.get          |  19 ++
 .../get/function.js                           |  19 ++
 .../getbulk/.env-cmdrc.js                     |  18 ++
 .../getbulk/Dockerfile.knative.state.getbulk  |  19 ++
 .../getbulk/function.js                       |  16 +
 .../knative-openfunction-state/manifests.yaml | 298 ++++++++++++++++++
 .../knative-openfunction-state/pg-values.yaml |   8 +
 .../query/.env-cmdrc.js                       |  18 ++
 .../query/Dockerfile.knative.state.query      |  19 ++
 .../query/function.js                         |  16 +
 .../save/.env-cmdrc.js                        |  18 ++
 .../save/Dockerfile.knative.state.save        |  19 ++
 .../save/function.js                          |  16 +
 .../transaction/.env-cmdrc.js                 |  18 ++
 .../Dockerfile.knative.state.transaction      |  19 ++
 .../transaction/function.js                   |  16 +
 test/e2e/knative-openfunction-state/verify.sh | 112 +++++++
 25 files changed, 871 insertions(+), 12 deletions(-)
 create mode 100644 test/e2e/knative-openfunction-state/delete/.env-cmdrc.js
 create mode 100644 test/e2e/knative-openfunction-state/delete/Dockerfile.knative.state.delete
 create mode 100644 test/e2e/knative-openfunction-state/delete/function.js
 create mode 100644 test/e2e/knative-openfunction-state/e2e.yaml
 create mode 100644 test/e2e/knative-openfunction-state/expected.data.yaml
 create mode 100644 test/e2e/knative-openfunction-state/get/.env-cmdrc.js
 create mode 100644 test/e2e/knative-openfunction-state/get/Dockerfile.knative.state.get
 create mode 100644 test/e2e/knative-openfunction-state/get/function.js
 create mode 100644 test/e2e/knative-openfunction-state/getbulk/.env-cmdrc.js
 create mode 100644 test/e2e/knative-openfunction-state/getbulk/Dockerfile.knative.state.getbulk
 create mode 100644 test/e2e/knative-openfunction-state/getbulk/function.js
 create mode 100644 test/e2e/knative-openfunction-state/manifests.yaml
 create mode 100644 test/e2e/knative-openfunction-state/pg-values.yaml
 create mode 100644 test/e2e/knative-openfunction-state/query/.env-cmdrc.js
 create mode 100644 test/e2e/knative-openfunction-state/query/Dockerfile.knative.state.query
 create mode 100644 test/e2e/knative-openfunction-state/query/function.js
 create mode 100644 test/e2e/knative-openfunction-state/save/.env-cmdrc.js
 create mode 100644 test/e2e/knative-openfunction-state/save/Dockerfile.knative.state.save
 create mode 100644 test/e2e/knative-openfunction-state/save/function.js
 create mode 100644 test/e2e/knative-openfunction-state/transaction/.env-cmdrc.js
 create mode 100644 test/e2e/knative-openfunction-state/transaction/Dockerfile.knative.state.transaction
 create mode 100644 test/e2e/knative-openfunction-state/transaction/function.js
 create mode 100644 test/e2e/knative-openfunction-state/verify.sh

diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml
index 847e8d54d..86ab1664c 100644
--- a/.github/workflows/e2e.yaml
+++ b/.github/workflows/e2e.yaml
@@ -2,14 +2,14 @@ name: Node.js E2E CI
 
 on:
   push:
-    branches: [ master ]
+    branches: [master]
     paths:
-      - '.github/workflows/**'
-      - 'docs/**'
-      - 'src/**'
-      - 'test/**'
-      - 'package.json'
-      - 'package-lock.json'
+      - ".github/workflows/**"
+      - "docs/**"
+      - "src/**"
+      - "test/**"
+      - "package.json"
+      - "package-lock.json"
   # pull_request:
   #   branches: [ master ]
   #   paths:
@@ -38,10 +38,12 @@ jobs:
           #   e2e: "test/e2e/knative-openfunction-bindings/e2e.yaml"
           # - name: knative openfunction pubsub e2e test
           #   e2e: "test/e2e/knative-openfunction-pubsub/e2e.yaml"
-          - name: async openfunction bindings e2e test
-            e2e: "test/e2e/async-openfunction-bindings/e2e.yaml"
-          - name: async openfunction pubsub e2e test
-            e2e: "test/e2e/async-openfunction-pubsub/e2e.yaml"
+          # - name: async openfunction bindings e2e test
+          #   e2e: "test/e2e/async-openfunction-bindings/e2e.yaml"
+          # - name: async openfunction pubsub e2e test
+          #   e2e: "test/e2e/async-openfunction-pubsub/e2e.yaml"
+          - name: knative openfunction state e2e test
+            e2e: "test/e2e/knative-openfunction-state/e2e.yaml"
     steps:
       - uses: actions/checkout@v2
 
@@ -52,7 +54,6 @@ jobs:
         run: |
           wget https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY}.tar.gz -O - |\
           tar xz && mv ${BINARY} /usr/local/bin/yq
-          
 
       - uses: apache/skywalking-infra-e2e@main
         with:
diff --git a/test/e2e/kind.yaml b/test/e2e/kind.yaml
index 2cabd9d07..aed7df0b6 100644
--- a/test/e2e/kind.yaml
+++ b/test/e2e/kind.yaml
@@ -31,3 +31,23 @@ nodes:
         # optional: set the protocol to one of TCP, UDP, SCTP.
         # TCP is the default
         protocol: TCP
+      - containerPort: 31235
+        hostPort: 81
+        listenAddress: "127.0.0.1"
+        protocol: TCP
+      - containerPort: 31236
+        hostPort: 82
+        listenAddress: "127.0.0.1"
+        protocol: TCP
+      - containerPort: 31237
+        hostPort: 83
+        listenAddress: "127.0.0.1"
+        protocol: TCP
+      - containerPort: 31238
+        hostPort: 84
+        listenAddress: "127.0.0.1"
+        protocol: TCP
+      - containerPort: 31239
+        hostPort: 85
+        listenAddress: "127.0.0.1"
+        protocol: TCP
\ No newline at end of file
diff --git a/test/e2e/knative-openfunction-state/delete/.env-cmdrc.js b/test/e2e/knative-openfunction-state/delete/.env-cmdrc.js
new file mode 100644
index 000000000..180f88046
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/delete/.env-cmdrc.js
@@ -0,0 +1,18 @@
+module.exports = {
+  knative: {
+    FUNC_CONTEXT: JSON.stringify({
+      name: 'my-knative-openfunction-state-delete-context',
+      version: '1.0.0',
+      runtime: 'knative',
+      states: {
+        // there is a policy, if you don't specify the state component, we will use the first one
+        // or you need specify the state name, then the context will use the one you specify
+        // hint : specify the name is the record key, not the component name
+        pg: {
+          componentName: 'knative-openfunction-state-component',
+          componentType: 'state.postgresql',
+        },
+      },
+    }),
+  },
+};
diff --git a/test/e2e/knative-openfunction-state/delete/Dockerfile.knative.state.delete b/test/e2e/knative-openfunction-state/delete/Dockerfile.knative.state.delete
new file mode 100644
index 000000000..f32a0e272
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/delete/Dockerfile.knative.state.delete
@@ -0,0 +1,19 @@
+# Use Node.js 14 as the base image
+FROM node:14
+
+# Set working directory
+WORKDIR /ff
+
+# Copy project files to container
+COPY package.json tsconfig.json /ff/
+COPY src /ff/src
+COPY test /ff/test
+
+# Install dependencies
+RUN npm install
+
+# Set working directory to /ff/test/e2e/knative-openfunction-state/delete
+WORKDIR /ff/test/e2e/knative-openfunction-state/delete
+
+# Run the ts-node command to execute src/main.ts
+CMD ["../../../../node_modules/.bin/env-cmd", "-e", "knative", "../../../../node_modules/.bin/ts-node", "../../../../src/main.ts", "--target=tryKnativeStateDelete","--signature-type=openfunction"]
\ No newline at end of file
diff --git a/test/e2e/knative-openfunction-state/delete/function.js b/test/e2e/knative-openfunction-state/delete/function.js
new file mode 100644
index 000000000..e5c6c9498
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/delete/function.js
@@ -0,0 +1,16 @@
+async function tryKnativeStateDelete(ctx, data) {
+  console.log('✅ Function should receive request: %o', data);
+  await ctx.state
+    .delete(data)
+    .then(res => {
+      console.log('✅ Success delete');
+      console.log(JSON.stringify(res));
+    })
+    .catch(err => {
+      console.log('❌ Failure occurred: %o', err);
+    });
+}
+
+module.exports = {
+  tryKnativeStateDelete,
+};
diff --git a/test/e2e/knative-openfunction-state/e2e.yaml b/test/e2e/knative-openfunction-state/e2e.yaml
new file mode 100644
index 000000000..3dae389b7
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/e2e.yaml
@@ -0,0 +1,90 @@
+setup:
+  env: kind
+  file: ../kind.yaml
+  steps:
+    - name: install dapr
+      command: |
+        dapr -v || (wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash)
+        dapr init -k -n dapr-system --runtime-version 1.11.0 --log-as-json --wait --timeout 600
+      wait:
+        - namespace: dapr-system
+          resource: pod
+          label-selector: app.kubernetes.io/name=dapr
+          for: condition=Ready
+
+    - name: install helm
+      command: |
+        curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
+
+    - name: install postgres
+      command: |
+        helm repo add bitnami https://charts.bitnami.com/bitnami
+        helm install postgres -n default bitnami/postgresql -f test/e2e/knative-openfunction-state/pg-values.yaml
+
+    # - name: build and load image
+    #   command: |
+    #     docker build -t knative-openfunction-state-save:latest -f test/e2e/knative-openfunction-state/save/Dockerfile.knative.state.save .
+    #     docker build -t knative-openfunction-state-get:latest -f test/e2e/knative-openfunction-state/get/Dockerfile.knative.state.get .
+    #     docker build -t knative-openfunction-state-getbulk:latest -f test/e2e/knative-openfunction-state/getbulk/Dockerfile.knative.state.getbulk .
+    #     docker build -t knative-openfunction-state-delete:latest -f test/e2e/knative-openfunction-state/delete/Dockerfile.knative.state.delete .
+    #     docker build -t knative-openfunction-state-transaction:latest -f test/e2e/knative-openfunction-state/transaction/Dockerfile.knative.state.transaction .
+    #     docker build -t knative-openfunction-state-query:latest -f test/e2e/knative-openfunction-state/query/Dockerfile.knative.state.query .
+    #     kind load docker-image knative-openfunction-state-save:latest
+    #     kind load docker-image knative-openfunction-state-get:latest
+    #     kind load docker-image knative-openfunction-state-getbulk:latest
+    #     kind load docker-image knative-openfunction-state-delete:latest
+    #     kind load docker-image knative-openfunction-state-transaction:latest
+    #     kind load docker-image knative-openfunction-state-query:latest
+    - name: build and load image
+      command: |
+        kind load docker-image knative-openfunction-state-save:latest
+        kind load docker-image knative-openfunction-state-get:latest
+        kind load docker-image knative-openfunction-state-getbulk:latest
+        kind load docker-image knative-openfunction-state-delete:latest
+        kind load docker-image knative-openfunction-state-transaction:latest
+        kind load docker-image knative-openfunction-state-query:latest
+
+    - name: setup manifests
+      path: manifests.yaml
+      wait:
+        - namespace: default
+          resource: deployment/knative-openfunction-state-get-deployment
+          for: condition=Available
+        - namespace: default
+          resource: deployment/knative-openfunction-state-save-deployment
+          for: condition=Available
+        - namespace: default
+          resource: deployment/knative-openfunction-state-getbulk-deployment
+          for: condition=Available
+        - namespace: default
+          resource: deployment/knative-openfunction-state-delete-deployment
+          for: condition=Available
+        - namespace: default
+          resource: deployment/knative-openfunction-state-transaction-deployment
+          for: condition=Available
+        - namespace: default
+          resource: deployment/knative-openfunction-state-query-deployment
+          for: condition=Available
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+
+  timeout: 60m
+
+cleanup:
+  # always never success failure
+  on: success
+
+trigger:
+  action: ""
+
+verify:
+  # verify with retry strategy
+  retry:
+    # max retry count
+    count: 60
+    # the interval between two attempts, e.g. 10s, 1m.
+    interval: 10s
+  cases:
+    - query: bash test/e2e/knative-openfunction-state/verify.sh 127.0.0.1 80 81 82 83 84 85| yq eval -P
+      expected: expected.data.yaml
diff --git a/test/e2e/knative-openfunction-state/expected.data.yaml b/test/e2e/knative-openfunction-state/expected.data.yaml
new file mode 100644
index 000000000..dc14570fb
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/expected.data.yaml
@@ -0,0 +1,9 @@
+results:
+  - key: "1"
+    data:
+      city: Seattle
+      state: WA
+      person:
+        id: "1036"
+        org: Dev Ops
+token: "1"
diff --git a/test/e2e/knative-openfunction-state/get/.env-cmdrc.js b/test/e2e/knative-openfunction-state/get/.env-cmdrc.js
new file mode 100644
index 000000000..4c66f604e
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/get/.env-cmdrc.js
@@ -0,0 +1,18 @@
+module.exports = {
+  knative: {
+    FUNC_CONTEXT: JSON.stringify({
+      name: 'my-knative-openfunction-state-get-context',
+      version: '1.0.0',
+      runtime: 'knative',
+      states: {
+        // there is a policy, if you don't specify the state component, we will use the first one
+        // or you need specify the state name, then the context will use the one you specify
+        // hint : specify the name is the record key, not the component name
+        pg: {
+          componentName: 'knative-openfunction-state-component',
+          componentType: 'state.postgresql',
+        },
+      },
+    }),
+  },
+};
diff --git a/test/e2e/knative-openfunction-state/get/Dockerfile.knative.state.get b/test/e2e/knative-openfunction-state/get/Dockerfile.knative.state.get
new file mode 100644
index 000000000..bf65da7b0
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/get/Dockerfile.knative.state.get
@@ -0,0 +1,19 @@
+# Use Node.js 14 as the base image
+FROM node:14
+
+# Set working directory
+WORKDIR /ff
+
+# Copy project files to container
+COPY package.json tsconfig.json /ff/
+COPY src /ff/src
+COPY test /ff/test
+
+# Install dependencies
+RUN npm install
+
+# Set working directory to /ff/test/e2e/knative-openfunction-state/get
+WORKDIR /ff/test/e2e/knative-openfunction-state/get
+
+# Run the ts-node command to execute src/main.ts
+CMD ["../../../../node_modules/.bin/env-cmd", "-e", "knative", "../../../../node_modules/.bin/ts-node", "../../../../src/main.ts", "--target=tryKnativeStateGet","--signature-type=openfunction"]
\ No newline at end of file
diff --git a/test/e2e/knative-openfunction-state/get/function.js b/test/e2e/knative-openfunction-state/get/function.js
new file mode 100644
index 000000000..be1ee0bcb
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/get/function.js
@@ -0,0 +1,19 @@
+async function tryKnativeStateGet(ctx, data) {
+  console.log('✅ Function should receive request: %o', data);
+  await ctx.state
+    .get(data)
+    .then(res => {
+      console.log('✅ Success get');
+      res.results.forEach(result => {
+        delete result.etag;
+      });
+      console.log(JSON.stringify(res));
+    })
+    .catch(err => {
+      console.log('❌ Failure occurred: %o', err);
+    });
+}
+
+module.exports = {
+  tryKnativeStateGet,
+};
diff --git a/test/e2e/knative-openfunction-state/getbulk/.env-cmdrc.js b/test/e2e/knative-openfunction-state/getbulk/.env-cmdrc.js
new file mode 100644
index 000000000..d4eb61afd
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/getbulk/.env-cmdrc.js
@@ -0,0 +1,18 @@
+module.exports = {
+  knative: {
+    FUNC_CONTEXT: JSON.stringify({
+      name: 'my-knative-openfunction-state-getbulk-context',
+      version: '1.0.0',
+      runtime: 'knative',
+      states: {
+        // there is a policy, if you don't specify the state component, we will use the first one
+        // or you need specify the state name, then the context will use the one you specify
+        // hint : specify the name is the record key, not the component name
+        pg: {
+          componentName: 'knative-openfunction-state-component',
+          componentType: 'state.postgresql',
+        },
+      },
+    }),
+  },
+};
diff --git a/test/e2e/knative-openfunction-state/getbulk/Dockerfile.knative.state.getbulk b/test/e2e/knative-openfunction-state/getbulk/Dockerfile.knative.state.getbulk
new file mode 100644
index 000000000..b0d5b4747
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/getbulk/Dockerfile.knative.state.getbulk
@@ -0,0 +1,19 @@
+# Use Node.js 14 as the base image
+FROM node:14
+
+# Set working directory
+WORKDIR /ff
+
+# Copy project files to container
+COPY package.json tsconfig.json /ff/
+COPY src /ff/src
+COPY test /ff/test
+
+# Install dependencies
+RUN npm install
+
+# Set working directory to /ff/test/e2e/knative-openfunction-state/getbulk
+WORKDIR /ff/test/e2e/knative-openfunction-state/getbulk
+
+# Run the ts-node command to execute src/main.ts
+CMD ["../../../../node_modules/.bin/env-cmd", "-e", "knative", "../../../../node_modules/.bin/ts-node", "../../../../src/main.ts", "--target=tryKnativeStateGetBulk","--signature-type=openfunction"]
\ No newline at end of file
diff --git a/test/e2e/knative-openfunction-state/getbulk/function.js b/test/e2e/knative-openfunction-state/getbulk/function.js
new file mode 100644
index 000000000..8475985d5
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/getbulk/function.js
@@ -0,0 +1,16 @@
+async function tryKnativeStateGetBulk(ctx, data) {
+  console.log('✅ Function should receive request: %o', data);
+  await ctx.state
+    .getBulk(data)
+    .then(res => {
+      console.log('✅ Success getBulk');
+      console.log(JSON.stringify(res));
+    })
+    .catch(err => {
+      console.log('❌ Failure occurred: %o', err);
+    });
+}
+
+module.exports = {
+  tryKnativeStateGetBulk,
+};
diff --git a/test/e2e/knative-openfunction-state/manifests.yaml b/test/e2e/knative-openfunction-state/manifests.yaml
new file mode 100644
index 000000000..2ce528e45
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/manifests.yaml
@@ -0,0 +1,298 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: knative-openfunction-state-save-deployment
+  labels:
+    app: knative-openfunction-state-save
+    case: knative
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: knative-openfunction-state-save
+      case: knative
+  template:
+    metadata:
+      labels:
+        app: knative-openfunction-state-save
+        case: knative
+      annotations:
+        dapr.io/enabled: "true"
+        dapr.io/app-id: "knative-openfunction-state-app"
+        dapr.io/app-port: "8080"
+        dapr.io/log-as-json: "true"
+        dapr.io/app-protocol: "http" # GRPC is not well supported so far in Dapr Node.js SDK
+    spec:
+      containers:
+        - name: my-knative-openfunction-state-save
+          image: knative-openfunction-state-save:latest
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8080
+              name: function-port
+              protocol: TCP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: knative-openfunction-state-get-deployment
+  labels:
+    app: knative-openfunction-state-get
+    case: knative
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: knative-openfunction-state-get
+      case: knative
+  template:
+    metadata:
+      labels:
+        app: knative-openfunction-state-get
+        case: knative
+      annotations:
+        dapr.io/enabled: "true"
+        dapr.io/app-id: "knative-openfunction-state-app"
+        dapr.io/app-port: "8080"
+        dapr.io/log-as-json: "true"
+        dapr.io/app-protocol: "http" # GRPC is not well supported so far in Dapr Node.js SDK
+    spec:
+      containers:
+        - name: my-knative-openfunction-state-get
+          image: knative-openfunction-state-get:latest
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8080
+              name: function-port
+              protocol: TCP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: knative-openfunction-state-getbulk-deployment
+  labels:
+    app: knative-openfunction-state-getbulk
+    case: knative
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: knative-openfunction-state-getbulk
+      case: knative
+  template:
+    metadata:
+      labels:
+        app: knative-openfunction-state-getbulk
+        case: knative
+      annotations:
+        dapr.io/enabled: "true"
+        dapr.io/app-id: "knative-openfunction-state-app"
+        dapr.io/app-port: "8080"
+        dapr.io/log-as-json: "true"
+        dapr.io/app-protocol: "http" # GRPC is not well supported so far in Dapr Node.js SDK
+    spec:
+      containers:
+        - name: my-knative-openfunction-state-getbulk
+          image: knative-openfunction-state-getbulk:latest
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8080
+              name: function-port
+              protocol: TCP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: knative-openfunction-state-delete-deployment
+  labels:
+    app: knative-openfunction-state-delete
+    case: knative
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: knative-openfunction-state-delete
+      case: knative
+  template:
+    metadata:
+      labels:
+        app: knative-openfunction-state-delete
+        case: knative
+      annotations:
+        dapr.io/enabled: "true"
+        dapr.io/app-id: "knative-openfunction-state-app"
+        dapr.io/app-port: "8080"
+        dapr.io/log-as-json: "true"
+        dapr.io/app-protocol: "http" # GRPC is not well supported so far in Dapr Node.js SDK
+    spec:
+      containers:
+        - name: my-knative-openfunction-state-delete
+          image: knative-openfunction-state-delete:latest
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8080
+              name: function-port
+              protocol: TCP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: knative-openfunction-state-transaction-deployment
+  labels:
+    app: knative-openfunction-state-transaction
+    case: knative
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: knative-openfunction-state-transaction
+      case: knative
+  template:
+    metadata:
+      labels:
+        app: knative-openfunction-state-transaction
+        case: knative
+      annotations:
+        dapr.io/enabled: "true"
+        dapr.io/app-id: "knative-openfunction-state-app"
+        dapr.io/app-port: "8080"
+        dapr.io/log-as-json: "true"
+        dapr.io/app-protocol: "http" # GRPC is not well supported so far in Dapr Node.js SDK
+    spec:
+      containers:
+        - name: my-knative-openfunction-state-transaction
+          image: knative-openfunction-state-transaction:latest
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8080
+              name: function-port
+              protocol: TCP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: knative-openfunction-state-query-deployment
+  labels:
+    app: knative-openfunction-state-query
+    case: knative
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: knative-openfunction-state-query
+      case: knative
+  template:
+    metadata:
+      labels:
+        app: knative-openfunction-state-query
+        case: knative
+      annotations:
+        dapr.io/enabled: "true"
+        dapr.io/app-id: "knative-openfunction-state-app"
+        dapr.io/app-port: "8080"
+        dapr.io/log-as-json: "true"
+        dapr.io/app-protocol: "http" # GRPC is not well supported so far in Dapr Node.js SDK
+    spec:
+      containers:
+        - name: my-knative-openfunction-state-query
+          image: knative-openfunction-state-query:latest
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8080
+              name: function-port
+              protocol: TCP
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: knative-openfunction-state-save-service
+spec:
+  type: NodePort
+  selector:
+    app: knative-openfunction-state-save
+  ports:
+    - protocol: TCP
+      port: 12345
+      targetPort: 8080
+      nodePort: 31234
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: knative-openfunction-state-get-service
+spec:
+  type: NodePort
+  selector:
+    app: knative-openfunction-state-get
+  ports:
+    - protocol: TCP
+      port: 12346
+      targetPort: 8080
+      nodePort: 31235
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: knative-openfunction-state-getbulk-service
+spec:
+  type: NodePort
+  selector:
+    app: knative-openfunction-state-getbulk
+  ports:
+    - protocol: TCP
+      port: 12347
+      targetPort: 8080
+      nodePort: 31236
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: knative-openfunction-state-delete-service
+spec:
+  type: NodePort
+  selector:
+    app: knative-openfunction-state-delete
+  ports:
+    - protocol: TCP
+      port: 12348
+      targetPort: 8080
+      nodePort: 31237
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: knative-openfunction-state-transaction-service
+spec:
+  type: NodePort
+  selector:
+    app: knative-openfunction-state-transaction
+  ports:
+    - protocol: TCP
+      port: 12349
+      targetPort: 8080
+      nodePort: 31238
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: knative-openfunction-state-query-service
+spec:
+  type: NodePort
+  selector:
+    app: knative-openfunction-state-query
+  ports:
+    - protocol: TCP
+      port: 12350
+      targetPort: 8080
+      nodePort: 31239
+---
+apiVersion: dapr.io/v1alpha1
+kind: Component
+metadata:
+  name: knative-openfunction-state-component
+spec:
+  type: state.postgresql
+  version: v1
+  metadata:
+    - name: connectionString
+      value: "host=postgres-postgresql user=postgres password=password port=5432 connect_timeout=10"
diff --git a/test/e2e/knative-openfunction-state/pg-values.yaml b/test/e2e/knative-openfunction-state/pg-values.yaml
new file mode 100644
index 000000000..5acc68d66
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/pg-values.yaml
@@ -0,0 +1,8 @@
+image:
+  repository: bitnami/postgresql
+  tag: 15.4.0-debian-11-r0
+
+global:
+  postgresql:
+    auth:
+      postgresPassword: password
diff --git a/test/e2e/knative-openfunction-state/query/.env-cmdrc.js b/test/e2e/knative-openfunction-state/query/.env-cmdrc.js
new file mode 100644
index 000000000..557623ba0
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/query/.env-cmdrc.js
@@ -0,0 +1,18 @@
+module.exports = {
+  knative: {
+    FUNC_CONTEXT: JSON.stringify({
+      name: 'my-knative-openfunction-state-query-context',
+      version: '1.0.0',
+      runtime: 'knative',
+      states: {
+        // there is a policy, if you don't specify the state component, we will use the first one
+        // or you need specify the state name, then the context will use the one you specify
+        // hint : specify the name is the record key, not the component name
+        pg: {
+          componentName: 'knative-openfunction-state-component',
+          componentType: 'state.postgresql',
+        },
+      },
+    }),
+  },
+};
diff --git a/test/e2e/knative-openfunction-state/query/Dockerfile.knative.state.query b/test/e2e/knative-openfunction-state/query/Dockerfile.knative.state.query
new file mode 100644
index 000000000..de02ca958
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/query/Dockerfile.knative.state.query
@@ -0,0 +1,19 @@
+# Use Node.js 14 as the base image
+FROM node:14
+
+# Set working directory
+WORKDIR /ff
+
+# Copy project files to container
+COPY package.json tsconfig.json /ff/
+COPY src /ff/src
+COPY test /ff/test
+
+# Install dependencies
+RUN npm install
+
+# Set working directory to /ff/test/e2e/knative-openfunction-state/query
+WORKDIR /ff/test/e2e/knative-openfunction-state/query
+
+# Run the ts-node command to execute src/main.ts
+CMD ["../../../../node_modules/.bin/env-cmd", "-e", "knative", "../../../../node_modules/.bin/ts-node", "../../../../src/main.ts", "--target=tryKnativeStateQuery","--signature-type=openfunction"]
\ No newline at end of file
diff --git a/test/e2e/knative-openfunction-state/query/function.js b/test/e2e/knative-openfunction-state/query/function.js
new file mode 100644
index 000000000..286b3d640
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/query/function.js
@@ -0,0 +1,16 @@
+async function tryKnativeStateQuery(ctx, data) {
+  console.log('✅ Function should receive request: %o', data);
+  await ctx.state
+    .query(data)
+    .then(res => {
+      console.log('✅ Success query');
+      console.log(JSON.stringify(res));
+    })
+    .catch(err => {
+      console.log('❌ Failure occurred: %o', err);
+    });
+}
+
+module.exports = {
+  tryKnativeStateQuery,
+};
diff --git a/test/e2e/knative-openfunction-state/save/.env-cmdrc.js b/test/e2e/knative-openfunction-state/save/.env-cmdrc.js
new file mode 100644
index 000000000..ac4a91b42
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/save/.env-cmdrc.js
@@ -0,0 +1,18 @@
+module.exports = {
+  knative: {
+    FUNC_CONTEXT: JSON.stringify({
+      name: 'my-knative-openfunction-state-save-context',
+      version: '1.0.0',
+      runtime: 'knative',
+      states: {
+        // there is a policy, if you don't specify the state component, we will use the first one
+        // or you need specify the state name, then the context will use the one you specify
+        // hint : specify the name is the record key, not the component name
+        pg: {
+          componentName: 'knative-openfunction-state-component',
+          componentType: 'state.postgresql',
+        },
+      },
+    }),
+  },
+};
diff --git a/test/e2e/knative-openfunction-state/save/Dockerfile.knative.state.save b/test/e2e/knative-openfunction-state/save/Dockerfile.knative.state.save
new file mode 100644
index 000000000..37f0172c0
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/save/Dockerfile.knative.state.save
@@ -0,0 +1,19 @@
+# Use Node.js 14 as the base image
+FROM node:14
+
+# Set working directory
+WORKDIR /ff
+
+# Copy project files to container
+COPY package.json tsconfig.json /ff/
+COPY src /ff/src
+COPY test /ff/test
+
+# Install dependencies
+RUN npm install
+
+# Set working directory to /ff/test/e2e/knative-openfunction-state/save
+WORKDIR /ff/test/e2e/knative-openfunction-state/save
+
+# Run the ts-node command to execute src/main.ts
+CMD ["../../../../node_modules/.bin/env-cmd", "-e", "knative", "../../../../node_modules/.bin/ts-node", "../../../../src/main.ts", "--target=tryKnativeStateSave","--signature-type=openfunction"]
\ No newline at end of file
diff --git a/test/e2e/knative-openfunction-state/save/function.js b/test/e2e/knative-openfunction-state/save/function.js
new file mode 100644
index 000000000..ec538e459
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/save/function.js
@@ -0,0 +1,16 @@
+async function tryKnativeStateSave(ctx, data) {
+  console.log('✅ Function should receive request: %o', data);
+  await ctx.state
+    .save(data)
+    .then(res => {
+      console.log('✅ Success query');
+      console.log(JSON.stringify(res));
+    })
+    .catch(err => {
+      console.log('❌ Failure occurred: %o', err);
+    });
+}
+
+module.exports = {
+  tryKnativeStateSave,
+};
diff --git a/test/e2e/knative-openfunction-state/transaction/.env-cmdrc.js b/test/e2e/knative-openfunction-state/transaction/.env-cmdrc.js
new file mode 100644
index 000000000..24606e8dc
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/transaction/.env-cmdrc.js
@@ -0,0 +1,18 @@
+module.exports = {
+  knative: {
+    FUNC_CONTEXT: JSON.stringify({
+      name: 'my-knative-openfunction-state-transaction-context',
+      version: '1.0.0',
+      runtime: 'knative',
+      states: {
+        // there is a policy, if you don't specify the state component, we will use the first one
+        // or you need specify the state name, then the context will use the one you specify
+        // hint : specify the name is the record key, not the component name
+        pg: {
+          componentName: 'knative-openfunction-state-component',
+          componentType: 'state.postgresql',
+        },
+      },
+    }),
+  },
+};
diff --git a/test/e2e/knative-openfunction-state/transaction/Dockerfile.knative.state.transaction b/test/e2e/knative-openfunction-state/transaction/Dockerfile.knative.state.transaction
new file mode 100644
index 000000000..b05cdccc1
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/transaction/Dockerfile.knative.state.transaction
@@ -0,0 +1,19 @@
+# Use Node.js 14 as the base image
+FROM node:14
+
+# Set working directory
+WORKDIR /ff
+
+# Copy project files to container
+COPY package.json tsconfig.json /ff/
+COPY src /ff/src
+COPY test /ff/test
+
+# Install dependencies
+RUN npm install
+
+# Set working directory to /ff/test/e2e/knative-openfunction-state/transaction
+WORKDIR /ff/test/e2e/knative-openfunction-state/transaction
+
+# Run the ts-node command to execute src/main.ts
+CMD ["../../../../node_modules/.bin/env-cmd", "-e", "knative", "../../../../node_modules/.bin/ts-node", "../../../../src/main.ts", "--target=tryKnativeStateTransaction","--signature-type=openfunction"]
\ No newline at end of file
diff --git a/test/e2e/knative-openfunction-state/transaction/function.js b/test/e2e/knative-openfunction-state/transaction/function.js
new file mode 100644
index 000000000..7e7096e8e
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/transaction/function.js
@@ -0,0 +1,16 @@
+async function tryKnativeStateTransaction(ctx, data) {
+  console.log('✅ Function should receive request: %o', data);
+  await ctx.state
+    .transaction(data)
+    .then(res => {
+      console.log('✅ Success transaction');
+      console.log(JSON.stringify(res));
+    })
+    .catch(err => {
+      console.log('❌ Failure occurred: %o', err);
+    });
+}
+
+module.exports = {
+  tryKnativeStateTransaction,
+};
diff --git a/test/e2e/knative-openfunction-state/verify.sh b/test/e2e/knative-openfunction-state/verify.sh
new file mode 100644
index 000000000..6ba28fe8c
--- /dev/null
+++ b/test/e2e/knative-openfunction-state/verify.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+
+ip=$1
+port1=$2
+port2=$3
+port3=$4
+port4=$5
+port5=$6
+port6=$7
+
+saveURL="http://$ip:$port1"
+getURL="http://$ip:$port2"
+getBulkURL="http://$ip:$port3"
+deleteURL="http://$ip:$port4"
+transactionURL="http://$ip:$port5"
+queryURL="http://$ip:$port6"
+
+headers="Content-Type: application/json"
+
+toSendSave='{
+  "data": [
+    {
+      "key": "1",
+      "value": {
+        "person": {
+          "org": "Dev Ops",
+          "id": 1036
+        },
+        "city": "Seattle",
+        "state": "WA"
+      }
+    },
+    {
+      "key": "2",
+      "value": {
+        "person": {
+          "org": "Hardware",
+          "id": 1028
+        },
+        "city": "Portland",
+        "state": "OR"
+      }
+    }
+  ]
+}'
+
+toSendGet='{
+  "key": "1"
+}'
+
+toSendGetBulk='{
+    "keys": ["1", "2"],
+    "parallelism": 10
+}'
+
+toSendDelete='{
+  "key": "1"
+}'
+
+toSendTransaction='{
+    "operations": [
+      {
+        "operation": "delete",
+        "request": {
+          "key": "2"
+        }
+      },
+      {
+        "operation": "upsert",
+        "request": {
+          "key": "1",
+          "value": {
+            "person": {
+              "org": "Dev Ops",
+              "id": "1036"
+            },
+            "city": "Seattle",
+            "state": "WA"
+          }
+        }
+      }
+    ]
+}'
+
+toSendQuery='{
+    "query": {
+      "filter": {
+        "EQ": {
+          "state": "WA"
+        }
+      },
+      "sort": [
+        {
+          "key": "person.id",
+          "order": "DESC"
+        }
+      ],
+      "page": {
+        "limit": 1
+      }
+    }
+}'
+
+curl -X POST -H "$headers" -d "$toSendSave" "$saveURL"
+curl -X POST -H "$headers" -d "$toSendGet" "$getURL"
+curl -X POST -H "$headers" -d "$toSendGetBulk" "$getBulkURL"
+curl -X POST -H "$headers" -d "$toSendDelete" "$deleteURL"
+curl -X POST -H "$headers" -d "$toSendTransaction" "$transactionURL"
+curl -X POST -H "$headers" -d "$toSendQuery" "$queryURL"
+
+data_result=$(KUBECONFIG=/tmp/e2e-k8s.config kubectl logs -l app="knative-openfunction-state-query" -c my-knative-openfunction-state-query --tail=2 | head -n 1)
+echo $data_result