From 19f64593308f6daeec94ab997de7dc592b389ae2 Mon Sep 17 00:00:00 2001 From: gezimbll Date: Thu, 27 Jul 2023 10:58:13 -0400 Subject: [PATCH] Improved coverage tests --- config/sentrypeercfg_test.go | 127 +++++++++++++++++++++++++++++++++++ engine/attributes_test.go | 109 ++++++++++++++++++++++++++++++ engine/filters_test.go | 119 ++++++++++++++++++++++++++++++++ 3 files changed, 355 insertions(+) create mode 100644 config/sentrypeercfg_test.go diff --git a/config/sentrypeercfg_test.go b/config/sentrypeercfg_test.go new file mode 100644 index 000000000..cec9d26b1 --- /dev/null +++ b/config/sentrypeercfg_test.go @@ -0,0 +1,127 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package config + +import ( + "reflect" + "testing" + + "github.com/cgrates/cgrates/utils" +) + +func TestSentryPeerCfgloadFromJsonCfg(t *testing.T) { + var sp, expected SentryPeerCfg + + if err := sp.loadFromJSONCfg(nil); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(sp, expected) { + t.Errorf("Expected %+v,Received %+v", expected, sp) + } + + cfgJsonStr := ` +{ + "sentrypeer":{ + "client_id":"sd5h7rhyrtudjj", + "client_secret":"w9buwnbw9ewbegsaovnmn9wr", + "token_url":"https://authz.sentrypeer.com/oauth/token", + "ips_url":"https://sentrypeer.com/api/ip-addresses", + "numbers_url":"https://sentrypeer.com/api/phone-numbers", + "audience":"https://sentrypeer.com/api", + "grant_type":"client_credentials", + } + } + ` + expected = SentryPeerCfg{ + ClientID: "sd5h7rhyrtudjj", + ClientSecret: "w9buwnbw9ewbegsaovnmn9wr", + TokenUrl: "https://authz.sentrypeer.com/oauth/token", + IpsUrl: "https://sentrypeer.com/api/ip-addresses", + NumbersUrl: "https://sentrypeer.com/api/phone-numbers", + Audience: "https://sentrypeer.com/api", + GrantType: "client_credentials", + } + cfgJson, err := NewCgrJsonCfgFromBytes([]byte(cfgJsonStr)) + if err != nil { + t.Error(err) + } + sentryPeerJson, err := cfgJson.SentryPeerJson() + if err != nil { + t.Error(err) + } + if err := sp.loadFromJSONCfg(sentryPeerJson); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(sp, expected) { + t.Errorf("Expected %+v,Received %+v", expected, sp) + } +} + +func TestSentryPeerAsMapInterface(t *testing.T) { + var sp SentryPeerCfg + cfgJsonStr := ` +{ + "sentrypeer":{ + "client_id": "sd5h7rhyrtudjj", + "client_secret": "w9buwnbw9ewbegsaovnmn9wr", + "token_url": "https://authz.sentrypeer.com/oauth/token", + "ips_url": "https://sentrypeer.com/api/ip-addresses", + "numbers_url": "https://sentrypeer.com/api/phone-numbers", + "audience": "https://sentrypeer.com/api", + "grant_type": "client_credentials", + } +} +` + expected := map[string]any{"ClientID": "sd5h7rhyrtudjj", + "ClientSecret": "w9buwnbw9ewbegsaovnmn9wr", + "TokenURL": "https://authz.sentrypeer.com/oauth/token", + "IpUrl": "https://sentrypeer.com/api/ip-addresses", + "NumberUrl": "https://sentrypeer.com/api/phone-numbers", + "Audience": "https://sentrypeer.com/api", + "GrantType": "client_credentials", + } + + cfgJson, err := NewCgrJsonCfgFromBytes([]byte(cfgJsonStr)) + if err != nil { + t.Error(err) + } + + sentryPeerJson, err := cfgJson.SentryPeerJson() + if err != nil { + t.Error(err) + } + if err := sp.loadFromJSONCfg(sentryPeerJson); err != nil { + t.Error(err) + } else if rcv := sp.AsMapInterface(); !reflect.DeepEqual(expected, rcv) { + t.Errorf("Expected %+v,Received %+v", utils.ToJSON(expected), utils.ToJSON(rcv)) + } +} + +func TestSentryPeerCfgClone(t *testing.T) { + + sp := &SentryPeerCfg{ + Audience: "https://sentrypeer.com/api", + GrantType: "client_credentials", + } + rcv := sp.Clone() + if !reflect.DeepEqual(rcv, sp) { + t.Errorf("Expected %+v,Received %+v", rcv, sp) + } + if rcv.GrantType = ""; sp.GrantType != "client_credentials" { + t.Error("Expected clone to not modify the cloned") + } +} diff --git a/engine/attributes_test.go b/engine/attributes_test.go index ad4755128..54fedb706 100644 --- a/engine/attributes_test.go +++ b/engine/attributes_test.go @@ -1442,3 +1442,112 @@ func TestAttrSV1GetAttributeForEvent(t *testing.T) { } } + +// func TestAttributesV1ProcessEventSentryPeer(t *testing.T) { +// testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// if r.Method == http.MethodPost { + +// if r.URL.EscapedPath() != "/oauth/token" { +// w.WriteHeader(http.StatusNotFound) +// return +// } +// contentType := r.Header.Get(utils.ContentType) +// if contentType != utils.JsonBody { +// w.WriteHeader(http.StatusBadRequest) +// return +// } +// var data map[string]string +// err := json.NewDecoder(r.Body).Decode(&data) +// if err != nil { +// w.WriteHeader(http.StatusBadRequest) +// return +// } +// response := struct { +// AccessToken string `json:"access_token"` +// }{ +// AccessToken: "302982309u2u30r23203", +// } +// w.WriteHeader(http.StatusOK) +// err = json.NewEncoder(w).Encode(response) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } +// return +// } +// if r.Method != http.MethodGet { +// w.WriteHeader(http.StatusMethodNotAllowed) +// return +// } +// responses := map[string]struct { +// code int +// body []byte +// }{ +// "/api/phone-numbers/100": {code: http.StatusOK, body: []byte(`{"IP Address found"}`)}, +// } +// if val, has := responses[r.URL.EscapedPath()]; has { +// w.WriteHeader(val.code) +// if val.body != nil { +// w.Write(val.body) +// } +// return +// } +// })) +// cfg := config.NewDefaultCGRConfig() +// cfg.SentryPeerCfg().ClientID = "ererwffwssf" +// cfg.SentryPeerCfg().ClientSecret = "3354rf43f34sf" +// cfg.SentryPeerCfg().TokenUrl = testServer.URL + "/oauth/token" +// cfg.SentryPeerCfg().IpsUrl = testServer.URL + "/api/ip-addresses" +// cfg.SentryPeerCfg().NumbersUrl = testServer.URL + "/api/phone-numbers" +// dm := NewDataManager(NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items), nil, nil) +// filterS := NewFilterS(cfg, nil, dm) + +// if err := dm.SetAttributeProfile(&AttributeProfile{ +// Tenant: "cgrates.org", +// ID: "ATTR_CHECK_DESTINATION", +// Contexts: []string{utils.MetaAny}, +// FilterIDs: []string{"*sentrypeer:~*req.Destination:*number"}, +// Attributes: []*Attribute{ +// { +// Path: "*req.Destination", +// Type: utils.MetaConstant, +// Value: config.NewRSRParsersMustCompile("BANNED_NUM", utils.InfieldSep), +// }}, +// Blocker: false, +// Weight: 20}, false); err != nil { +// t.Error(err) +// } + +// alS := NewAttributeService(dm, filterS, cfg) +// var rply AttrSProcessEventReply +// expected := AttrSProcessEventReply{ +// MatchedProfiles: []string{"cgrates.org:ATTR_CHECK_DESTINATION"}, +// AlteredFields: []string{"*req.Destination"}, +// CGREvent: &utils.CGREvent{ +// Tenant: "cgrates.org", +// Time: nil, +// Event: map[string]any{ +// utils.AccountField: "account_1001", +// utils.Destination: "BANNED_NUM", +// }, +// APIOpts: map[string]any{ +// utils.OptsAttributesProcessRuns: 2, +// }, +// }, +// blocker: false, +// } +// if err = alS.V1ProcessEvent(&utils.CGREvent{ +// Tenant: "cgrates.org", +// Event: map[string]any{ +// utils.AccountField: "account_1001", +// utils.Destination: "100", +// }, +// APIOpts: map[string]any{ +// utils.OptsAttributesProcessRuns: 2, +// }, +// }, &rply); err != nil { +// t.Errorf("Expected <%+v>, received <%+v>", nil, err) +// } else if sort.Strings(rply.AlteredFields); !reflect.DeepEqual(expected, rply) { +// t.Errorf("Expected <%+v>, received <%+v>", utils.ToJSON(expected), utils.ToJSON(rply)) +// } +// } diff --git a/engine/filters_test.go b/engine/filters_test.go index 21010a7c4..131cc81d8 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -19,6 +19,7 @@ along with this program. If not, see package engine import ( + "encoding/json" "fmt" "net/http" "net/http/httptest" @@ -2417,3 +2418,121 @@ func TestFilterLazyPassErr(t *testing.T) { t.Errorf(err.Error()) } } + +func TestSentryPeer(t *testing.T) { + token := "token27072023" + testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + + if r.URL.EscapedPath() != "/oauth/token" { + w.WriteHeader(http.StatusNotFound) + return + } + contentType := r.Header.Get(utils.ContentType) + if contentType != utils.JsonBody { + w.WriteHeader(http.StatusBadRequest) + return + } + var data map[string]string + err := json.NewDecoder(r.Body).Decode(&data) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + if data[utils.ClientIdCfg] != "ererwffwssf" || + data[utils.ClientSecretCfg] != "3354rf43f34sf" || + data[utils.AudienceCfg] != "https://sentrypeer.com/api" || + data[utils.GrantTypeCfg] != "client_credentials" { + w.WriteHeader(http.StatusBadRequest) + return + } + response := struct { + AccessToken string `json:"access_token"` + }{ + AccessToken: token, + } + w.WriteHeader(http.StatusOK) + err = json.NewEncoder(w).Encode(response) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + return + } + + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + responses := map[string]struct { + code int + body []byte + }{ + "/api/ip-addresses/1.2.3.254": {code: http.StatusNotFound, body: []byte(`{"IP Address not found"}`)}, + "/api/ip-addresses/184.168.31.232": {code: http.StatusOK, body: []byte(`{"IP Address found"}`)}, + "/api/phone-numbers/22663272712": {code: http.StatusNotFound, body: []byte(`Phone Number not found`)}, + "/api/phone-numbers/90046322651795": {code: http.StatusOK, body: []byte(`{"Phone Number found`)}, + } + if val, has := responses[r.URL.EscapedPath()]; has { + if r.Header.Get(utils.AuthorizationHdr) != utils.BearerAuth+" "+token { + w.WriteHeader(http.StatusUnauthorized) + return + } + w.WriteHeader(val.code) + if val.body != nil { + w.Write(val.body) + } + return + } + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(`Wrong path in the request`)) + })) + + defer testServer.Close() + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) + dm := NewDataManager(data, config.CgrConfig().CacheCfg(), nil) + filterS := FilterS{ + cfg: cfg, + dm: dm, + } + dp := utils.MapStorage{ + utils.MetaReq: utils.MapStorage{ + "BADIP": "184.168.31.232", + "IP": "1.2.3.254", + "Number": "22663272712", + "BadNumber": "90046322651795", + }, + } + config.CgrConfig().SentryPeerCfg().ClientID = "ererwffwssf" + config.CgrConfig().SentryPeerCfg().ClientSecret = "3354rf43f34sf" + config.CgrConfig().SentryPeerCfg().TokenUrl = testServer.URL + "/oauth/token" + config.CgrConfig().SentryPeerCfg().IpsUrl = testServer.URL + "/api/ip-addresses" + config.CgrConfig().SentryPeerCfg().NumbersUrl = testServer.URL + "/api/phone-numbers" + + if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.IP:*ip"}, dp); err != nil { + t.Error(err) + } else if !pass { + t.Error("Expected to pass") + } + + if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.BADIP:*ip"}, dp); err != nil { + t.Error(err) + } else if pass { + t.Error("Expected to not pass") + } + + if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.Number:*number"}, dp); err != nil { + t.Error(err) + } else if !pass { + t.Error("Expected to pass") + } + + if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.BadNumber:*number"}, dp); err != nil { + t.Error(err) + } else if pass { + t.Error("Expected to not pass") + } + +}