diff --git a/engine/attributes_test.go b/engine/attributes_test.go
new file mode 100644
index 000000000..93b32b6d2
--- /dev/null
+++ b/engine/attributes_test.go
@@ -0,0 +1,174 @@
+/*
+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 engine
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestAttributesShutdown(t *testing.T) {
+ alS := &AttributeService{}
+
+ utils.Logger.SetLogLevel(6)
+ utils.Logger.SetSyslog(nil)
+
+ var buf bytes.Buffer
+ log.SetOutput(&buf)
+ defer func() {
+ log.SetOutput(os.Stderr)
+ }()
+
+ exp := []string{
+ "CGRateS <> [INFO] shutdown initialized",
+ "CGRateS <> [INFO] shutdown complete",
+ }
+ alS.Shutdown()
+ rcv := strings.Split(buf.String(), "\n")
+
+ for i := 0; i < 2; i++ {
+ rcv[i] = rcv[i][20:]
+ if rcv[i] != exp[i] {
+ t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", exp[i], rcv[i])
+ }
+ }
+
+ utils.Logger.SetLogLevel(0)
+}
+
+func TestAttributesSetCloneable(t *testing.T) {
+ attr := &AttrArgsProcessEvent{
+ AttributeIDs: []string{"ATTR_ID"},
+ Context: utils.StringPointer(utils.MetaAny),
+ ProcessRuns: utils.IntPointer(1),
+ clnb: true,
+ }
+
+ exp := &AttrArgsProcessEvent{
+ AttributeIDs: []string{"ATTR_ID"},
+ Context: utils.StringPointer(utils.MetaAny),
+ ProcessRuns: utils.IntPointer(1),
+ clnb: false,
+ }
+ attr.SetCloneable(false)
+
+ if !reflect.DeepEqual(attr, exp) {
+ t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", exp, attr)
+ }
+}
+
+func TestAttributesRPCClone(t *testing.T) {
+ attr := &AttrArgsProcessEvent{
+ AttributeIDs: []string{"ATTR_ID"},
+ Context: utils.StringPointer(utils.MetaAny),
+ ProcessRuns: utils.IntPointer(1),
+ CGREvent: &utils.CGREvent{
+ Event: make(map[string]interface{}),
+ APIOpts: make(map[string]interface{}),
+ },
+ clnb: true,
+ }
+
+ rcv, err := attr.RPCClone()
+
+ exp := &AttrArgsProcessEvent{
+ AttributeIDs: []string{"ATTR_ID"},
+ Context: utils.StringPointer(utils.MetaAny),
+ ProcessRuns: utils.IntPointer(1),
+ CGREvent: &utils.CGREvent{
+ Event: make(map[string]interface{}),
+ APIOpts: make(map[string]interface{}),
+ },
+ clnb: false,
+ }
+
+ if err != nil {
+ t.Fatalf("\nexpected: <%+v>, \nreceived: <%+v>", nil, err)
+ }
+
+ if !reflect.DeepEqual(rcv, exp) {
+ t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", exp, rcv)
+ }
+
+}
+
+func TestAttributesV1GetAttributeForEventNilCGREvent(t *testing.T) {
+ alS := &AttributeService{}
+ args := &AttrArgsProcessEvent{}
+ reply := &AttributeProfile{}
+
+ experr := fmt.Sprintf("MANDATORY_IE_MISSING: [%s]", "CGREvent")
+ err := alS.V1GetAttributeForEvent(args, reply)
+
+ if err == nil || err.Error() != experr {
+ t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", experr, err)
+ }
+}
+
+func TestAttributesV1GetAttributeForEventProfileNotFound(t *testing.T) {
+ defaultCfg := config.NewDefaultCGRConfig()
+ db := NewInternalDB(nil, nil, true)
+ dm := NewDataManager(db, nil, nil)
+ alS := &AttributeService{
+ dm: dm,
+ filterS: &FilterS{},
+ cgrcfg: defaultCfg,
+ }
+ args := &AttrArgsProcessEvent{
+ CGREvent: &utils.CGREvent{},
+ }
+ reply := &AttributeProfile{}
+
+ experr := utils.ErrNotFound
+ err := alS.V1GetAttributeForEvent(args, reply)
+
+ if err == nil || err != experr {
+ t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", experr, err)
+ }
+}
+
+func TestAttributesV1GetAttributeForEvent2(t *testing.T) {
+ defaultCfg := config.NewDefaultCGRConfig()
+ db := NewInternalDB(nil, nil, true)
+ dm := NewDataManager(db, nil, nil)
+ alS := &AttributeService{
+ dm: dm,
+ filterS: &FilterS{},
+ cgrcfg: defaultCfg,
+ }
+ args := &AttrArgsProcessEvent{
+ CGREvent: &utils.CGREvent{},
+ }
+ reply := &AttributeProfile{}
+
+ experr := utils.ErrNotFound
+ err := alS.V1GetAttributeForEvent(args, reply)
+
+ if err == nil || err != experr {
+ t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", experr, err)
+ }
+}