diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..897f371
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,15 @@
+FROM registry.access.redhat.com/ubi8/ubi:8.1
+
+WORKDIR /tests
+
+COPY main.sh .
+COPY testcases/smoke_test.sh ./testcases/
+
+RUN yum -y install wget
+RUN yum -y install jq
+
+RUN wget https://github.com/mingrammer/flog/releases/download/v0.4.3/flog_0.4.3_linux_amd64.tar.gz \
+ && tar -xvf flog_0.4.3_linux_amd64.tar.gz \
+ && cp flog /usr/local/bin
+
+ENTRYPOINT ["./main.sh"]
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d1fccee
--- /dev/null
+++ b/README.md
@@ -0,0 +1,17 @@
+## Quest
+
+This repository contains integration tests and load generation tests for Parseable server. Tests are written in shell script and bundled in a container.
+
+### Build test container locally
+
+```
+docker build . -t parseable/test:edge
+```
+
+### Running tests
+
+Use the below format to run tests against a Parseable server. The first argument is the test name, the second argument is the server URL, the third argument is the username and the fourth argument is the password.
+
+```
+docker run parseable/test:edge smoke http://demo.parseable.io parseable parseable
+```
diff --git a/main.sh b/main.sh
new file mode 100644
index 0000000..c535903
--- /dev/null
+++ b/main.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Parseable Server (C) 2023 Cloudnatively Pvt. Ltd.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+
+mode=$1
+endpoint=$2
+username=$3
+password=$4
+
+run_smoke_test () {
+ stream_name=$(head /dev/urandom | tr -dc a-z | head -c10)
+ ./testcases/smoke_test.sh "$endpoint" "$stream_name" "$username" "$password"
+ return $?
+}
+
+case "$mode" in
+ "smoke") run_smoke_test
+ ;;
+esac
diff --git a/testcases/smoke-test.sh b/testcases/smoke-test.sh
new file mode 100644
index 0000000..bbbffb7
--- /dev/null
+++ b/testcases/smoke-test.sh
@@ -0,0 +1,300 @@
+#!/bin/sh
+#
+# Parseable Server (C) 2023 Cloudnatively Pvt. Ltd.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+
+parseable_url=$1
+stream_name=$2
+username=$3
+password=$4
+
+events=50
+input_file=$PWD/input.json
+
+curl_std_opts=( -sS --header 'Content-Type: application/json' -w '\n\n%{http_code}' -u "$username":"$password" )
+
+alert_body='{"alerts":[{"name":"server-fail-alert1","message":"server reported error status","rule":{"field":"http_status","contains":"500","repeats":5,"within":"10m"},"target":[{"name":"slack-target","server_url":"http://mailgun.com","api_key":"xxxx"}]}]}'
+
+schema_body='{"fields":[{"name":"host","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"user-identifier","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"datetime","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"method","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"request","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"protocol","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"status","data_type":"Int64","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"bytes","data_type":"Int64","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"referer","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false},{"name":"labels","data_type":"Utf8","nullable":true,"dict_id":0,"dict_is_ordered":false}]}'
+
+# Generate events using flog (https://github.com/mingrammer/flog) and store it in input.json file
+create_input_file () {
+ flog -f json -n "$events" -t log -o "$input_file"
+ sleep 2
+ sed -i '1s/^/[/;$!s/$/,/;$s/$/]/' "$input_file"
+ return $?
+}
+
+# Create stream
+create_stream () {
+ response=$(curl "${curl_std_opts[@]}" --request PUT "$parseable_url"/api/v1/logstream/"$stream_name")
+
+ if [ $? -ne 0 ]; then
+ printf "Failed to create log stream %s with exit code: %s\n" "$stream_name" "$?"
+ printf "Test create_stream: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to create log stream %s with http code: %s and response: %s\n" "$stream_name" "$http_code" "$content"
+ printf "Test create_stream: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ if [ "$content" != "Created log stream $stream_name" ]; then
+ printf "Failed to create log stream $stream_name with response: %s\n" "$content"
+ printf "Test create_stream: failed\n"
+ exit 1
+ fi
+
+ printf "Test create_stream: successful\n"
+ return 0
+}
+
+# Post log data to the stream
+post_event_data () {
+ create_input_file
+ if [ $? -ne 0 ]; then
+ printf "Failed to create log data to be posted to %s with exit code: %s\n" "$stream_name" "$?"
+ printf "Test post_event_data: failed\n"
+ exit 1
+ fi
+
+ content=$(cat "$input_file")
+ response=$(curl "${curl_std_opts[@]}" --request POST "$parseable_url"/api/v1/logstream/"$stream_name" --data-raw "$content")
+ if [ $? -ne 0 ]; then
+ printf "Failed to post log data to %s with exit code: %s\n" "$stream_name" "$?"
+ printf "Test post_event_data: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to create log stream %s with http code: %s and response: %s\n" "$stream_name" "$http_code" "$content"
+ printf "Test post_event_data: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ if [ "$content" != "Successfully posted $events events" ]; then
+ printf "Failed to post log data to %s with response: %s\n" "$stream_name" "$content"
+ printf "Test post_event_data: failed\n"
+ exit 1
+ fi
+
+ printf "Test post_event_data: successful\n"
+ return 0
+}
+
+# List all log stream and [TODO] verify if the stream is created
+list_log_streams () {
+ response=$(curl "${curl_std_opts[@]}" --request GET "$parseable_url"/api/v1/logstream)
+ if [ $? -ne 0 ]; then
+ printf "Failed to list log streams with exit code: %s\n" "$?"
+ printf "Test list_log_streams: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to list all log streams with http code: %s and response: %s" "$http_code" "$content"
+ printf "Test list_log_streams: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ echo "$content" > "$PWD/log_streams.json"
+
+ if [ "$(jq < $PWD/log_streams.json '[.[].name | select(. == "'"$stream_name"'")] | length')" -ne 1 ]; then
+ printf "Failed to find new log stream %s in list stream result: %s\n" "$stream_name" "$content"
+ printf "Test list_log_streams: failed\n"
+ exit 1
+ fi
+
+ printf "Test list_log_streams: successful\n"
+ return 0
+}
+
+# Get Stream's schema and [TODO] validate its schema
+get_streams_schema () {
+ response=$(curl "${curl_std_opts[@]}" --request GET "$parseable_url"/api/v1/logstream/"$stream_name"/schema)
+ if [ $? -ne 0 ]; then
+ printf "Failed to fetch stream schema with exit code: %s\n" "$?"
+ printf "Test get_streams_schema: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to get schema for stream %s with http code: %s and response: %s" "$stream_name" "$http_code" "$content"
+ printf "Test get_streams_schema: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ if [ "$content" != "$schema_body" ]; then
+ printf "Get schema response doesn't match with expected schema.\n"
+ printf "Schema expected: %s\n" "$schema_body"
+ printf "Schema returned: %s\n" "$content"
+ printf "Test get_streams_schema: failed\n"
+ exit 1
+ fi
+
+ printf "Test get_streams_schema: successful\n"
+ return 0
+}
+
+# Query the log stream and verify if count of events is equal to the number of events posted
+query_log_stream() {
+ # Query last two minutes of data only
+ end_time=$(date "+%Y-%m-%dT%H:%M:%S%:z")
+ start_time=$(date --date="@$(($(date +%s)-120))" "+%Y-%m-%dT%H:%M:%S%:z")
+
+ response=$(curl "${curl_std_opts[@]}" --request POST "$parseable_url"/api/v1/query --data-raw '{
+ "query": "select count(*) from '$stream_name'",
+ "startTime": "'$start_time'",
+ "endTime": "'$end_time'"
+ }')
+ if [ $? -ne 0 ]; then
+ printf "Failed to query log data from %s with exit code: %s\n" "$stream_name" "$?"
+ printf "Test query_log_stream: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to query stream %s with http code: %s and response: %s" "$stream_name" "$http_code" "$content"
+ printf "Test query_log_stream: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ queryResult=$(echo "$content" | cut -d ':' -f2 | cut -d '}' -f1)
+ if [ "$queryResult" != $events ]; then
+ printf "Validation failed. Count of events returned from query does not match with the ones posted.\n"
+ printf "Test query_log_stream: failed\n"
+ exit 1
+ fi
+ printf "Test query_log_stream: successful\n"
+ return 0
+}
+
+# Set Alert
+set_alert () {
+ response=$(curl "${curl_std_opts[@]}" --request PUT "$parseable_url"/api/v1/logstream/"$stream_name"/alert --data-raw "$alert_body")
+ if [ $? -ne 0 ]; then
+ printf "Failed to set alert for %s with exit code: %s\n" "$stream_name" "$?"
+ printf "Test set_alert: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to set alert for %s with http code: %s and response: %s\n" "$stream_name" "$http_code" "$content"
+ printf "Test set_alert: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ if [ "$content" != "Set alert configuration for log stream $stream_name" ]; then
+ printf "Failed to set alert on log stream %s with response: %s\n" "$stream_name" "$content"
+ printf "Test set_alert: failed\n"
+ exit 1
+ fi
+
+ printf "Test set_alert: successful\n"
+ return 0
+}
+
+# Get Alert
+get_alert () {
+ response=$(curl "${curl_std_opts[@]}" --request GET "$parseable_url"/api/v1/logstream/"$stream_name"/alert)
+ if [ $? -ne 0 ]; then
+ printf "Failed to get alert for %s with exit code: %s\n" "$stream_name" "$?"
+ printf "Test get_alert: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to get alert for %s with http code: %s and response: %s" "$stream_name" "$http_code" "$content"
+ printf "Test get_alert: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ if [ "$content" != "$alert_body" ]; then
+ printf "Get alert response doesn't match with Alert config returned.\n"
+ printf "Alert set: %s\n" "$alert_body"
+ printf "Alert returned: %s\n" "$content"
+ printf "Test get_alert: failed\n"
+ exit 1
+ fi
+
+ printf "Test get_alert: successful\n"
+ return 0
+}
+
+# Delete stream
+delete_stream () {
+ response=$(curl "${curl_std_opts[@]}" --request DELETE "$parseable_url"/api/v1/logstream/"$stream_name")
+
+ if [ $? -ne 0 ]; then
+ printf "Failed to delete stream for %s with exit code: %s\n" "$stream_name" "$?"
+ printf "Test delete_stream: failed\n"
+ exit 1
+ fi
+
+ http_code=$(tail -n1 <<< "$response")
+ if [ "$http_code" -ne 200 ]; then
+ printf "Failed to delete log stream %s with http code: %s and response: %s\n" "$stream_name" "$http_code" "$content"
+ printf "Test delete_stream: failed\n"
+ exit 1
+ fi
+
+ content=$(sed '$ d' <<< "$response")
+ if [ "$content" != "log stream $stream_name deleted" ]; then
+ printf "Failed to delete log stream %s with response: %s" "$stream_name" "$content"
+ printf "Test delete_stream: failed\n"
+ exit 1
+ fi
+
+ printf "Test delete_stream: successful\n"
+ return 0
+}
+
+cleanup () {
+ rm -rf "$input_file"
+ rm -rf "$PWD/logstream_test.json"
+ return $?
+}
+
+printf "======= Starting smoke tests =======\n"
+printf "** Log stream name: %s **\n" "$stream_name"
+printf "** Event count: %s **\n" "$events"
+printf "====================================\n"
+create_stream
+post_event_data
+list_log_streams
+get_streams_schema
+query_log_stream
+set_alert
+get_alert
+delete_stream
+cleanup
+printf "======= Smoke tests completed ======\n"