|
@@ -1,12 +1,18 @@
|
|
|
package apiserver
|
|
|
|
|
|
import (
|
|
|
+ "fmt"
|
|
|
+ "os"
|
|
|
"testing"
|
|
|
- "time"
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
)
|
|
|
|
|
|
+const (
|
|
|
+ APIKEY = "apikey"
|
|
|
+ PASSWORD = "password"
|
|
|
+)
|
|
|
+
|
|
|
func TestDeleteDecisionRange(t *testing.T) {
|
|
|
lapi := SetupLAPITest(t)
|
|
|
|
|
@@ -14,20 +20,20 @@ func TestDeleteDecisionRange(t *testing.T) {
|
|
|
lapi.InsertAlertFromFile("./tests/alert_minibulk.json")
|
|
|
|
|
|
// delete by ip wrong
|
|
|
- w := lapi.RecordResponse("DELETE", "/v1/decisions?range=1.2.3.0/24", emptyBody, "password")
|
|
|
+ w := lapi.RecordResponse("DELETE", "/v1/decisions?range=1.2.3.0/24", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
|
|
|
assert.Equal(t, `{"nbDeleted":"0"}`, w.Body.String())
|
|
|
|
|
|
// delete by range
|
|
|
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions?range=91.121.79.0/24&contains=false", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions?range=91.121.79.0/24&contains=false", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
assert.Equal(t, `{"nbDeleted":"2"}`, w.Body.String())
|
|
|
|
|
|
// delete by range : ensure it was already deleted
|
|
|
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions?range=91.121.79.0/24", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions?range=91.121.79.0/24", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
assert.Equal(t, `{"nbDeleted":"0"}`, w.Body.String())
|
|
|
}
|
|
@@ -40,19 +46,19 @@ func TestDeleteDecisionFilter(t *testing.T) {
|
|
|
|
|
|
// delete by ip wrong
|
|
|
|
|
|
- w := lapi.RecordResponse("DELETE", "/v1/decisions?ip=1.2.3.4", emptyBody, "password")
|
|
|
+ w := lapi.RecordResponse("DELETE", "/v1/decisions?ip=1.2.3.4", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
assert.Equal(t, `{"nbDeleted":"0"}`, w.Body.String())
|
|
|
|
|
|
// delete by ip good
|
|
|
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions?ip=91.121.79.179", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions?ip=91.121.79.179", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
assert.Equal(t, `{"nbDeleted":"1"}`, w.Body.String())
|
|
|
|
|
|
// delete by scope/value
|
|
|
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions?scopes=Ip&value=91.121.79.178", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions?scopes=Ip&value=91.121.79.178", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
assert.Equal(t, `{"nbDeleted":"1"}`, w.Body.String())
|
|
|
}
|
|
@@ -65,7 +71,7 @@ func TestGetDecisionFilters(t *testing.T) {
|
|
|
|
|
|
// Get Decision
|
|
|
|
|
|
- w := lapi.RecordResponse("GET", "/v1/decisions", emptyBody, "apikey")
|
|
|
+ w := lapi.RecordResponse("GET", "/v1/decisions", emptyBody, APIKEY)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
decisions, code, err := readDecisionsGetResp(w)
|
|
|
assert.Nil(t, err)
|
|
@@ -80,7 +86,7 @@ func TestGetDecisionFilters(t *testing.T) {
|
|
|
|
|
|
// Get Decision : type filter
|
|
|
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions?type=ban", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions?type=ban", emptyBody, APIKEY)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
decisions, code, err = readDecisionsGetResp(w)
|
|
|
assert.Nil(t, err)
|
|
@@ -98,7 +104,7 @@ func TestGetDecisionFilters(t *testing.T) {
|
|
|
|
|
|
// Get Decision : scope/value
|
|
|
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions?scopes=Ip&value=91.121.79.179", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions?scopes=Ip&value=91.121.79.179", emptyBody, APIKEY)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
decisions, code, err = readDecisionsGetResp(w)
|
|
|
assert.Nil(t, err)
|
|
@@ -113,7 +119,7 @@ func TestGetDecisionFilters(t *testing.T) {
|
|
|
|
|
|
// Get Decision : ip filter
|
|
|
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions?ip=91.121.79.179", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions?ip=91.121.79.179", emptyBody, APIKEY)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
decisions, code, err = readDecisionsGetResp(w)
|
|
|
assert.Nil(t, err)
|
|
@@ -127,7 +133,7 @@ func TestGetDecisionFilters(t *testing.T) {
|
|
|
// assert.NotContains(t, w.Body.String(), `"id":2,"origin":"crowdsec","scenario":"crowdsecurity/ssh-bf","scope":"Ip","type":"ban","value":"91.121.79.178"`)
|
|
|
|
|
|
// Get decision : by range
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions?range=91.121.79.0/24&contains=false", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions?range=91.121.79.0/24&contains=false", emptyBody, APIKEY)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
decisions, code, err = readDecisionsGetResp(w)
|
|
|
assert.Nil(t, err)
|
|
@@ -145,7 +151,7 @@ func TestGetDecision(t *testing.T) {
|
|
|
lapi.InsertAlertFromFile("./tests/alert_sample.json")
|
|
|
|
|
|
// Get Decision
|
|
|
- w := lapi.RecordResponse("GET", "/v1/decisions", emptyBody, "apikey")
|
|
|
+ w := lapi.RecordResponse("GET", "/v1/decisions", emptyBody, APIKEY)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
decisions, code, err := readDecisionsGetResp(w)
|
|
|
assert.Nil(t, err)
|
|
@@ -165,7 +171,7 @@ func TestGetDecision(t *testing.T) {
|
|
|
assert.Equal(t, int64(3), decisions[2].ID)
|
|
|
|
|
|
// Get Decision with invalid filter. It should ignore this filter
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions?test=test", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions?test=test", emptyBody, APIKEY)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
assert.Equal(t, 3, len(decisions))
|
|
|
}
|
|
@@ -177,49 +183,49 @@ func TestDeleteDecisionByID(t *testing.T) {
|
|
|
lapi.InsertAlertFromFile("./tests/alert_sample.json")
|
|
|
|
|
|
//Have one alerts
|
|
|
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
+ w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, APIKEY)
|
|
|
decisions, code, err := readDecisionsStreamResp(w)
|
|
|
assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
+ assert.Equal(t, 200, code)
|
|
|
+ assert.Equal(t, 0, len(decisions["deleted"]))
|
|
|
+ assert.Equal(t, 1, len(decisions["new"]))
|
|
|
|
|
|
// Delete alert with Invalid ID
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/test", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions/test", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 400, w.Code)
|
|
|
err_resp, _, err := readDecisionsErrorResp(w)
|
|
|
assert.NoError(t, err)
|
|
|
- assert.Equal(t, err_resp["message"], "decision_id must be valid integer")
|
|
|
+ assert.Equal(t, "decision_id must be valid integer", err_resp["message"])
|
|
|
|
|
|
// Delete alert with ID that not exist
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/100", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions/100", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 500, w.Code)
|
|
|
err_resp, _, err = readDecisionsErrorResp(w)
|
|
|
assert.NoError(t, err)
|
|
|
- assert.Equal(t, err_resp["message"], "decision with id '100' doesn't exist: unable to delete")
|
|
|
+ assert.Equal(t, "decision with id '100' doesn't exist: unable to delete", err_resp["message"])
|
|
|
|
|
|
//Have one alerts
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, APIKEY)
|
|
|
decisions, code, err = readDecisionsStreamResp(w)
|
|
|
assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
+ assert.Equal(t, 200, code)
|
|
|
+ assert.Equal(t, 0, len(decisions["deleted"]))
|
|
|
+ assert.Equal(t, 1, len(decisions["new"]))
|
|
|
|
|
|
// Delete alert with valid ID
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
resp, _, err := readDecisionsDeleteResp(w)
|
|
|
assert.NoError(t, err)
|
|
|
assert.Equal(t, resp.NbDeleted, "1")
|
|
|
|
|
|
//Have one alert (because we delete an alert that has dup targets)
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, APIKEY)
|
|
|
decisions, code, err = readDecisionsStreamResp(w)
|
|
|
assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
+ assert.Equal(t, 200, code)
|
|
|
+ assert.Equal(t, 0, len(decisions["deleted"]))
|
|
|
+ assert.Equal(t, 1, len(decisions["new"]))
|
|
|
}
|
|
|
|
|
|
func TestDeleteDecision(t *testing.T) {
|
|
@@ -229,14 +235,14 @@ func TestDeleteDecision(t *testing.T) {
|
|
|
lapi.InsertAlertFromFile("./tests/alert_sample.json")
|
|
|
|
|
|
// Delete alert with Invalid filter
|
|
|
- w := lapi.RecordResponse("DELETE", "/v1/decisions?test=test", emptyBody, "password")
|
|
|
+ w := lapi.RecordResponse("DELETE", "/v1/decisions?test=test", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 500, w.Code)
|
|
|
err_resp, _, err := readDecisionsErrorResp(w)
|
|
|
assert.NoError(t, err)
|
|
|
assert.Equal(t, err_resp["message"], "'test' doesn't exist: invalid filter")
|
|
|
|
|
|
// Delete all alert
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
resp, _, err := readDecisionsDeleteResp(w)
|
|
|
assert.NoError(t, err)
|
|
@@ -251,181 +257,1061 @@ func TestStreamStartDecisionDedup(t *testing.T) {
|
|
|
lapi.InsertAlertFromFile("./tests/alert_sample.json")
|
|
|
|
|
|
// Get Stream, we only get one decision (the longest one)
|
|
|
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
+ w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, APIKEY)
|
|
|
decisions, code, err := readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(3))
|
|
|
- assert.Equal(t, *decisions["new"][0].Origin, "test")
|
|
|
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
|
|
|
+ assert.Equal(t, nil, err)
|
|
|
+ assert.Equal(t, 200, code)
|
|
|
+ assert.Equal(t, 0, len(decisions["deleted"]))
|
|
|
+ assert.Equal(t, 1, len(decisions["new"]))
|
|
|
+ assert.Equal(t, int64(3), decisions["new"][0].ID)
|
|
|
+ assert.Equal(t, "test", *decisions["new"][0].Origin)
|
|
|
+ assert.Equal(t, "127.0.0.1", *decisions["new"][0].Value)
|
|
|
|
|
|
// id=3 decision is deleted, this won't affect `deleted`, because there are decisions on the same ip
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/3", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions/3", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
|
|
|
// Get Stream, we only get one decision (the longest one, id=2)
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, APIKEY)
|
|
|
decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(2))
|
|
|
- assert.Equal(t, *decisions["new"][0].Origin, "test")
|
|
|
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
|
|
|
+ assert.Equal(t, nil, err)
|
|
|
+ assert.Equal(t, 200, code)
|
|
|
+ assert.Equal(t, 0, len(decisions["deleted"]))
|
|
|
+ assert.Equal(t, 1, len(decisions["new"]))
|
|
|
+ assert.Equal(t, int64(2), decisions["new"][0].ID)
|
|
|
+ assert.Equal(t, "test", *decisions["new"][0].Origin)
|
|
|
+ assert.Equal(t, "127.0.0.1", *decisions["new"][0].Value)
|
|
|
|
|
|
// We delete another decision, yet don't receive it in stream, since there's another decision on same IP
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/2", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions/2", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
|
|
|
// And get the remaining decision (1)
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, APIKEY)
|
|
|
decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(1))
|
|
|
- assert.Equal(t, *decisions["new"][0].Origin, "test")
|
|
|
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
|
|
|
+ assert.Equal(t, nil, err)
|
|
|
+ assert.Equal(t, 200, code)
|
|
|
+ assert.Equal(t, 0, len(decisions["deleted"]))
|
|
|
+ assert.Equal(t, 1, len(decisions["new"]))
|
|
|
+ assert.Equal(t, int64(1), decisions["new"][0].ID)
|
|
|
+ assert.Equal(t, "test", *decisions["new"][0].Origin)
|
|
|
+ assert.Equal(t, "127.0.0.1", *decisions["new"][0].Value)
|
|
|
|
|
|
// We delete the last decision, we receive the delete order
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody, "password")
|
|
|
+ w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody, PASSWORD)
|
|
|
assert.Equal(t, 200, w.Code)
|
|
|
|
|
|
//and now we only get a deleted decision
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
+ w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, APIKEY)
|
|
|
decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 1)
|
|
|
- assert.Equal(t, decisions["deleted"][0].ID, int64(1))
|
|
|
- assert.Equal(t, *decisions["deleted"][0].Origin, "test")
|
|
|
- assert.Equal(t, *decisions["deleted"][0].Value, "127.0.0.1")
|
|
|
- assert.Equal(t, len(decisions["new"]), 0)
|
|
|
+ assert.Equal(t, nil, err)
|
|
|
+ assert.Equal(t, 200, code)
|
|
|
+ assert.Equal(t, 1, len(decisions["deleted"]))
|
|
|
+ assert.Equal(t, int64(1), decisions["deleted"][0].ID)
|
|
|
+ assert.Equal(t, "test", *decisions["deleted"][0].Origin)
|
|
|
+ assert.Equal(t, "127.0.0.1", *decisions["deleted"][0].Value)
|
|
|
+ assert.Equal(t, 0, len(decisions["new"]))
|
|
|
}
|
|
|
|
|
|
-func TestStreamDecisionDedup(t *testing.T) {
|
|
|
- //Ensure that at stream startup we only get the longest decision
|
|
|
- lapi := SetupLAPITest(t)
|
|
|
-
|
|
|
- // Create Valid Alert : 3 decisions for 127.0.0.1, longest has id=3
|
|
|
- lapi.InsertAlertFromFile("./tests/alert_sample.json")
|
|
|
-
|
|
|
- time.Sleep(2 * time.Second)
|
|
|
-
|
|
|
- // Get Stream, we only get one decision (the longest one)
|
|
|
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
- decisions, code, err := readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(3))
|
|
|
- assert.Equal(t, *decisions["new"][0].Origin, "test")
|
|
|
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
|
|
|
-
|
|
|
- // id=3 decision is deleted, this won't affect `deleted`, because there are decisions on the same ip
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/3", emptyBody, "password")
|
|
|
- assert.Equal(t, 200, w.Code)
|
|
|
-
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream", emptyBody, "apikey")
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 0)
|
|
|
- // We delete another decision, yet don't receive it in stream, since there's another decision on same IP
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/2", emptyBody, "password")
|
|
|
- assert.Equal(t, 200, w.Code)
|
|
|
-
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream", emptyBody, "apikey")
|
|
|
- decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 0)
|
|
|
-
|
|
|
- // We delete the last decision, we receive the delete order
|
|
|
- w = lapi.RecordResponse("DELETE", "/v1/decisions/1", emptyBody, "password")
|
|
|
- assert.Equal(t, 200, w.Code)
|
|
|
-
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream", emptyBody, "apikey")
|
|
|
- decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, code, 200)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 1)
|
|
|
- assert.Equal(t, decisions["deleted"][0].ID, int64(1))
|
|
|
- assert.Equal(t, *decisions["deleted"][0].Origin, "test")
|
|
|
- assert.Equal(t, *decisions["deleted"][0].Value, "127.0.0.1")
|
|
|
- assert.Equal(t, len(decisions["new"]), 0)
|
|
|
+type DecisionCheck struct {
|
|
|
+ ID int64
|
|
|
+ Origin string
|
|
|
+ Scenario string
|
|
|
+ Value string
|
|
|
+ Duration string
|
|
|
+ Type string
|
|
|
}
|
|
|
|
|
|
-func TestStreamDecisionFilters(t *testing.T) {
|
|
|
+type DecisionTest struct {
|
|
|
+ TestName string
|
|
|
+ Method string
|
|
|
+ Route string
|
|
|
+ CheckCodeOnly bool
|
|
|
+ Code int
|
|
|
+ LenNew int
|
|
|
+ LenDeleted int
|
|
|
+ NewChecks []DecisionCheck
|
|
|
+ DelChecks []DecisionCheck
|
|
|
+ AuthType string
|
|
|
+}
|
|
|
|
|
|
+func TestStreamDecisionStart(t *testing.T) {
|
|
|
lapi := SetupLAPITest(t)
|
|
|
|
|
|
- // Create Valid Alert
|
|
|
- lapi.InsertAlertFromFile("./tests/alert_stream_fixture.json")
|
|
|
-
|
|
|
- w := lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true", emptyBody, "apikey")
|
|
|
- decisions, code, err := readDecisionsStreamResp(w)
|
|
|
-
|
|
|
- assert.Equal(t, 200, code)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 3)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(1))
|
|
|
- assert.Equal(t, *decisions["new"][0].Origin, "test1")
|
|
|
- assert.Equal(t, *decisions["new"][0].Value, "127.0.0.1")
|
|
|
- assert.Equal(t, *decisions["new"][0].Scenario, "crowdsecurity/http_bf")
|
|
|
- assert.Equal(t, decisions["new"][1].ID, int64(2))
|
|
|
- assert.Equal(t, *decisions["new"][1].Origin, "test2")
|
|
|
- assert.Equal(t, *decisions["new"][1].Value, "127.0.0.1")
|
|
|
- assert.Equal(t, *decisions["new"][1].Scenario, "crowdsecurity/ssh_bf")
|
|
|
- assert.Equal(t, decisions["new"][2].ID, int64(3))
|
|
|
- assert.Equal(t, *decisions["new"][2].Origin, "test3")
|
|
|
- assert.Equal(t, *decisions["new"][2].Value, "127.0.0.1")
|
|
|
- assert.Equal(t, *decisions["new"][2].Scenario, "crowdsecurity/ddos")
|
|
|
-
|
|
|
- // test filter scenarios_not_containing
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&scenarios_not_containing=http", emptyBody, "apikey")
|
|
|
- decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, 200, code)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 2)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(2))
|
|
|
- assert.Equal(t, decisions["new"][1].ID, int64(3))
|
|
|
-
|
|
|
- // test filter scenarios_containing
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&scenarios_containing=http", emptyBody, "apikey")
|
|
|
- decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, 200, code)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(1))
|
|
|
+ /*
|
|
|
+ Create multiple alerts:
|
|
|
+ - 3 alerts for 127.0.0.1 with ID 1/2/3 : Different duration / scenario / origin
|
|
|
+ - 3 alerts for 127.0.0.2 with ID 4/5/6/7 : Different duration / scenario / origin
|
|
|
+ */
|
|
|
+ lapi.InsertAlertFromFile("./tests/alert_duplicate.json")
|
|
|
+
|
|
|
+ tests := []DecisionTest{
|
|
|
+ {
|
|
|
+ TestName: "test startup",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(3),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/longest",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "4h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with scenarios containing",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&scenarios_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 2,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(5),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with multiple scenarios containing",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&scenarios_containing=ssh_bf,test",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with unknown scenarios containing",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&scenarios_containing=unknown",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with scenarios containing and not containing",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&scenarios_containing=test&scenarios_not_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(1),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "59m",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with scenarios containing and not containing 2",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&scenarios_containing=longest&scenarios_not_containing=ssh_bf,test",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 1,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(3),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/longest",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "4h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with scenarios not containing",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&scenarios_not_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(3),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/longest",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "4h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with multiple scenarios not containing",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&scenarios_not_containing=ssh_bf,test",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 1,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(3),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/longest",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "4h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with origins parameter",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&origins=another_origin",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 2,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(7),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "1h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with multiple origins parameter",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&origins=another_origin,test",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(3),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/longest",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "4h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "test startup with unknown origins",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true&origins=unknown",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 3 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/3",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not in deleted IP",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 2 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/2",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not in deleted IP",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(1),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 1 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/1",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "127.0.0.1 should be in deleted now",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 2,
|
|
|
+ LenDeleted: 1,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(1),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "-", // we check that the time is negative
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, test := range tests {
|
|
|
+ runTest(lapi, test, t)
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- // test filters both by scenarios_not_containing and scenarios_containing
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&scenarios_not_containing=ssh&scenarios_containing=ddos", emptyBody, "apikey")
|
|
|
- decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, 200, code)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 1)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(3))
|
|
|
+func TestStreamDecision(t *testing.T) {
|
|
|
+
|
|
|
+ /*
|
|
|
+ Create multiple alerts:
|
|
|
+ - 3 alerts for 127.0.0.1 with ID 1/2/3 : Different duration / scenario / origin
|
|
|
+ - 3 alerts for 127.0.0.2 with ID 4/5/6/7 : Different duration / scenario / origin
|
|
|
+ */
|
|
|
+
|
|
|
+ // this test just init the stream with startup=true
|
|
|
+ preTests := []DecisionTest{
|
|
|
+ {
|
|
|
+ TestName: "test startup",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?startup=true",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ tests := map[string][]DecisionTest{
|
|
|
+ "Test without parameter": {
|
|
|
+ {
|
|
|
+ TestName: "get stream",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(3),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/longest",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "4h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 3 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/3",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not in deleted IP",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 2 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/2",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not in deleted IP",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 1 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/1",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "127.0.0.1 should be in deleted now",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 1,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(1),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "-",
|
|
|
+
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "test with scenarios containing": {
|
|
|
+ {
|
|
|
+ TestName: "get stream",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?scenarios_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 2,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(5),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 3 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/3",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not in deleted IP",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?scenarios_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 2 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/2",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is deleted (decision for ssh_bf was with ID 2)",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?scenarios_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 1,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "-",
|
|
|
+
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "test with scenarios not containing": {
|
|
|
+ {
|
|
|
+ TestName: "get stream",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?scenarios_not_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 3,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(3),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/longest",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "4h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(4),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(8),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "captcha",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 3 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/3",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not in deleted IP",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?scenarios_not_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 2 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/2",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not deleted",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?scenarios_not_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 1 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/1",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is deleted",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?scenarios_not_containing=ssh_bf",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 1,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(1),
|
|
|
+ Origin: "test",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "-",
|
|
|
+
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "test with origins": {
|
|
|
+ {
|
|
|
+ TestName: "get stream",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?origins=another_origin",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 2,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "2h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ID: int64(7),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/test",
|
|
|
+ Value: "127.0.0.2",
|
|
|
+ Duration: "1h59",
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 3 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/3",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is not in deleted IP",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?origins=another_origin",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "delete decisions 2 (127.0.0.1)",
|
|
|
+ Method: "DELETE",
|
|
|
+ Route: "/v1/decisions/2",
|
|
|
+ CheckCodeOnly: true,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 0,
|
|
|
+ AuthType: PASSWORD,
|
|
|
+ DelChecks: []DecisionCheck{},
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ TestName: "check that 127.0.0.1 is deleted",
|
|
|
+ Method: "GET",
|
|
|
+ Route: "/v1/decisions/stream?origins=another_origin",
|
|
|
+ CheckCodeOnly: false,
|
|
|
+ Code: 200,
|
|
|
+ LenNew: 0,
|
|
|
+ LenDeleted: 1,
|
|
|
+ AuthType: APIKEY,
|
|
|
+ DelChecks: []DecisionCheck{
|
|
|
+ {
|
|
|
+ ID: int64(2),
|
|
|
+ Origin: "another_origin",
|
|
|
+ Scenario: "crowdsecurity/ssh_bf",
|
|
|
+ Value: "127.0.0.1",
|
|
|
+ Duration: "-",
|
|
|
+
|
|
|
+ Type: "ban",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ NewChecks: []DecisionCheck{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ // run tests for the stream
|
|
|
+ for testName, test := range tests {
|
|
|
+
|
|
|
+ // init a new LAPI
|
|
|
+ lapi := SetupLAPITest(t)
|
|
|
+
|
|
|
+ // run pre-test, mostly to init the stream
|
|
|
+ for _, test := range preTests {
|
|
|
+ runTest(lapi, test, t)
|
|
|
+ }
|
|
|
+ // insert decisions now that the stream is initiated
|
|
|
+ lapi.InsertAlertFromFile("./tests/alert_duplicate.json")
|
|
|
+
|
|
|
+ for _, oneTest := range test {
|
|
|
+ oneTest.TestName = fmt.Sprintf("%s (%s)", oneTest.TestName, testName)
|
|
|
+ runTest(lapi, oneTest, t)
|
|
|
+ }
|
|
|
+
|
|
|
+ // clean the db after each test
|
|
|
+ os.Remove(lapi.DBConfig.DbPath)
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- // test filter by origin
|
|
|
- w = lapi.RecordResponse("GET", "/v1/decisions/stream?startup=true&origins=test1,test2", emptyBody, "apikey")
|
|
|
- decisions, code, err = readDecisionsStreamResp(w)
|
|
|
- assert.Equal(t, err, nil)
|
|
|
- assert.Equal(t, 200, code)
|
|
|
- assert.Equal(t, len(decisions["deleted"]), 0)
|
|
|
- assert.Equal(t, len(decisions["new"]), 2)
|
|
|
- assert.Equal(t, decisions["new"][0].ID, int64(1))
|
|
|
- assert.Equal(t, decisions["new"][1].ID, int64(2))
|
|
|
+func runTest(lapi LAPI, test DecisionTest, t *testing.T) {
|
|
|
+ w := lapi.RecordResponse(test.Method, test.Route, emptyBody, test.AuthType)
|
|
|
+ assert.Equal(t, test.Code, w.Code)
|
|
|
+ if test.CheckCodeOnly {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ decisions, _, err := readDecisionsStreamResp(w)
|
|
|
+ assert.Equal(t, nil, err)
|
|
|
+ assert.Equal(t, test.LenDeleted, len(decisions["deleted"]), fmt.Sprintf("'%s': len(deleted)", test.TestName))
|
|
|
+ assert.Equal(t, test.LenNew, len(decisions["new"]), fmt.Sprintf("'%s': len(new)", test.TestName))
|
|
|
+
|
|
|
+ for i, check := range test.NewChecks {
|
|
|
+ assert.Equal(t, check.ID, decisions["new"][i].ID, fmt.Sprintf("'%s' (idx: %d): field: ID", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Origin, *decisions["new"][i].Origin, fmt.Sprintf("'%s' (idx: %d): field: Origin", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Scenario, *decisions["new"][i].Scenario, fmt.Sprintf("'%s' (idx: %d): field: Scenario", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Value, *decisions["new"][i].Value, fmt.Sprintf("'%s' (idx: %d): field: Value", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Type, *decisions["new"][i].Type, fmt.Sprintf("'%s' (idx: %d): field: Type", test.TestName, i))
|
|
|
+ assert.Contains(t, *decisions["new"][i].Duration, check.Duration, fmt.Sprintf("'%s' (idx: %d): field: Duration", test.TestName, i))
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, check := range test.DelChecks {
|
|
|
+ assert.Equal(t, check.ID, decisions["deleted"][i].ID, fmt.Sprintf("'%s' (idx: %d): field: ID", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Origin, *decisions["deleted"][i].Origin, fmt.Sprintf("'%s' (idx: %d): field: Origin", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Scenario, *decisions["deleted"][i].Scenario, fmt.Sprintf("'%s' (idx: %d): field: Scenario", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Value, *decisions["deleted"][i].Value, fmt.Sprintf("'%s' (idx: %d): field: Value", test.TestName, i))
|
|
|
+ assert.Equal(t, check.Type, *decisions["deleted"][i].Type, fmt.Sprintf("'%s' (idx: %d): field: Type", test.TestName, i))
|
|
|
+ assert.Contains(t, *decisions["deleted"][i].Duration, check.Duration, fmt.Sprintf("'%s' (idx: %d): field: Duration", test.TestName, i))
|
|
|
+ }
|
|
|
}
|