diff --git a/ees/filecsv_test.go b/ees/filecsv_test.go
index a31c78b07..1aa06a45e 100644
--- a/ees/filecsv_test.go
+++ b/ees/filecsv_test.go
@@ -61,6 +61,7 @@ type nopCloser struct {
}
func (nopCloser) Close() error { return nil }
+
func TestFileCsvComposeHeader(t *testing.T) {
cgrCfg := config.NewDefaultCGRConfig()
newIDb := engine.NewInternalDB(nil, nil, true)
@@ -269,5 +270,72 @@ func TestFileCsvExportEvent(t *testing.T) {
if err := fCsv.ExportEvent(cgrEv); err == nil || err.Error() != errExpect {
t.Errorf("Expected %q but received %q", errExpect, err)
}
+}
+
+func TestFileCsvOnEvictedTrailer(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ byteBuff := new(bytes.Buffer)
+ csvNW := csv.NewWriter(byteBuff)
+ fCsv := &FileCSVee{
+ id: "string",
+ cgrCfg: cgrCfg,
+ cfgIdx: 0,
+ filterS: filterS,
+ file: nopCloserWrite{byteBuff},
+ csvWriter: csvNW,
+ dc: utils.MapStorage{},
+ }
+ cgrCfg.EEsCfg().Exporters[fCsv.cfgIdx].Fields = []*config.FCTemplate{
+ {
+ Path: "*trl.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field1", utils.InfieldSep),
+ Filters: []string{"*wrong-type"},
+ },
+ {
+ Path: "*trl.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field2", utils.InfieldSep),
+ Filters: []string{"*wrong-type"},
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[fCsv.cfgIdx].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[fCsv.cfgIdx].ComputeFields()
+ fCsv.OnEvicted("test", "test")
+}
+
+func TestFileCsvOnEvictedClose(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ byteBuff := new(bytes.Buffer)
+ csvNW := csv.NewWriter(byteBuff)
+ fCsv := &FileCSVee{
+ id: "string",
+ cgrCfg: cgrCfg,
+ cfgIdx: 0,
+ filterS: filterS,
+ file: nopCloserError{byteBuff},
+ csvWriter: csvNW,
+ dc: utils.MapStorage{},
+ }
+ cgrCfg.EEsCfg().Exporters[fCsv.cfgIdx].Fields = []*config.FCTemplate{
+ {
+ Path: "*trl.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field1", utils.InfieldSep),
+ },
+ {
+ Path: "*trl.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field2", utils.InfieldSep),
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[fCsv.cfgIdx].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[fCsv.cfgIdx].ComputeFields()
fCsv.OnEvicted("test", "test")
}
diff --git a/ees/filefwv_test.go b/ees/filefwv_test.go
index eb7020e38..343d8a510 100644
--- a/ees/filefwv_test.go
+++ b/ees/filefwv_test.go
@@ -21,6 +21,7 @@ package ees
import (
"bytes"
"encoding/csv"
+ "io"
"reflect"
"testing"
@@ -125,7 +126,6 @@ func TestFileFwvComposeHeader(t *testing.T) {
if err := fFwv.composeHeader(); err == nil || err.Error() != errExpect {
t.Errorf("Expected %q but received %q", errExpect, err)
}
-
}
func TestFileFwvComposeTrailer(t *testing.T) {
@@ -270,3 +270,182 @@ func TestFileFwvExportEvent(t *testing.T) {
t.Errorf("Expected %q but received %q", errExpect, err)
}
}
+
+type nopCloserWrite struct {
+ io.Writer
+}
+
+func (nopCloserWrite) Close() error { return nil }
+func (nopCloserWrite) Write(s []byte) (n int, err error) {
+ return 0, utils.ErrNotImplemented
+}
+
+func TestFileFwvExportEventWriteError(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ cgrEv := new(utils.CGREvent)
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ byteBuff := new(bytes.Buffer)
+ dc, err := newEEMetrics(utils.FirstNonEmpty(
+ "Local",
+ utils.EmptyString,
+ ))
+ if err != nil {
+ t.Error(err)
+ }
+ fFwv := &FileFWVee{
+ id: "string",
+ cgrCfg: cgrCfg,
+ cfgIdx: 0,
+ filterS: filterS,
+ file: nopCloserWrite{byteBuff},
+ dc: dc,
+ }
+ cgrEv.Event = map[string]interface{}{
+ "test1": "value",
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields = []*config.FCTemplate{{}}
+ for _, field := range cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].ComputeFields()
+ if err := fFwv.ExportEvent(cgrEv); err == nil || err != utils.ErrNotImplemented {
+ t.Errorf("Expected %q but received %q", utils.ErrNotImplemented, err)
+ }
+}
+
+func TestFileFwvComposeHeaderWriteError(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ byteBuff := new(bytes.Buffer)
+ fFwv := &FileFWVee{
+ id: "string",
+ cgrCfg: cgrCfg,
+ cfgIdx: 0,
+ filterS: filterS,
+ file: nopCloserWrite{byteBuff},
+ dc: utils.MapStorage{},
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields = []*config.FCTemplate{
+ {
+ Path: "*hdr.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field1", utils.InfieldSep),
+ },
+ {
+ Path: "*hdr.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field2", utils.InfieldSep),
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].ComputeFields()
+ if err := fFwv.composeHeader(); err == nil || err != utils.ErrNotImplemented {
+ t.Errorf("Expected %q but received %q", utils.ErrNotImplemented, err)
+ }
+}
+
+func TestFileFwvComposeTrailerWriteError(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ byteBuff := new(bytes.Buffer)
+ fFwv := &FileFWVee{
+ id: "string",
+ cgrCfg: cgrCfg,
+ cfgIdx: 0,
+ filterS: filterS,
+ file: nopCloserWrite{byteBuff},
+ dc: utils.MapStorage{},
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields = []*config.FCTemplate{
+ {
+ Path: "*trl.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field1", utils.InfieldSep),
+ },
+ {
+ Path: "*trl.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field2", utils.InfieldSep),
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].ComputeFields()
+ if err := fFwv.composeTrailer(); err == nil || err != utils.ErrNotImplemented {
+ t.Errorf("Expected %q but received %q", utils.ErrNotImplemented, err)
+ }
+}
+func TestFileFwvOnEvictedTrailer(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ byteBuff := new(bytes.Buffer)
+ fFwv := &FileFWVee{
+ id: "string",
+ cgrCfg: cgrCfg,
+ cfgIdx: 0,
+ filterS: filterS,
+ file: nopCloserWrite{byteBuff},
+ dc: utils.MapStorage{},
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields = []*config.FCTemplate{
+ {
+ Path: "*trl.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field1", utils.InfieldSep),
+ },
+ {
+ Path: "*trl.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field2", utils.InfieldSep),
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].ComputeFields()
+ fFwv.OnEvicted("test", "test")
+}
+
+type nopCloserError struct {
+ io.Writer
+}
+
+func (nopCloserError) Close() error { return utils.ErrNotImplemented }
+func (nopCloserError) Write(s []byte) (n int, err error) {
+ return 0, utils.ErrNotImplemented
+}
+func TestFileFwvOnEvictedClose(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ byteBuff := new(bytes.Buffer)
+ fFwv := &FileFWVee{
+ id: "string",
+ cgrCfg: cgrCfg,
+ cfgIdx: 0,
+ filterS: filterS,
+ file: nopCloserError{byteBuff},
+ dc: utils.MapStorage{},
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields = []*config.FCTemplate{
+ {
+ Path: "*trl.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field1", utils.InfieldSep),
+ },
+ {
+ Path: "*trl.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("field2", utils.InfieldSep),
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[fFwv.cfgIdx].ComputeFields()
+ fFwv.OnEvicted("test", "test")
+}
diff --git a/ees/httpjsonmap_test.go b/ees/httpjsonmap_test.go
index 25f8e87a9..5a42e1139 100644
--- a/ees/httpjsonmap_test.go
+++ b/ees/httpjsonmap_test.go
@@ -19,6 +19,9 @@ along with this program. If not, see
package ees
import (
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
"reflect"
"testing"
@@ -53,7 +56,7 @@ func TestHttpJsonMapGetMetrics(t *testing.T) {
}
}
-func TestHttpJsonMapExportEvent(t *testing.T) {
+func TestHttpJsonMapExportEvent1(t *testing.T) {
cgrCfg := config.NewDefaultCGRConfig()
cgrCfg.EEsCfg().Exporters[0].Type = utils.MetaSQSjsonMap
cgrEv := new(utils.CGREvent)
@@ -139,9 +142,78 @@ func TestHttpJsonMapExportEvent(t *testing.T) {
if err := httpEE.ExportEvent(cgrEv); err == nil || err.Error() != errExpect {
t.Errorf("Expected %q but received %q", errExpect, err)
}
+ //test marshal invalid input
+ cgrEv.Event = map[string]interface{}{
+ "test": make(chan int),
+ }
+ cgrCfg.EEsCfg().Exporters[0].Fields = []*config.FCTemplate{{}}
+ for _, field := range cgrCfg.EEsCfg().Exporters[0].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[0].ComputeFields()
+ errExpect = "json: unsupported type: chan int"
+ if err := httpEE.ExportEvent(cgrEv); err == nil || err.Error() != errExpect {
+ t.Errorf("Expected %q but received %q", errExpect, err)
+ }
httpEE.OnEvicted("test", "test")
}
+func TestHttpJsonMapExportEvent2(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ cgrCfg.EEsCfg().Exporters[0].Type = utils.MetaSQSjsonMap
+ cgrEv := new(utils.CGREvent)
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ dc, err := newEEMetrics(utils.FirstNonEmpty(
+ "Local",
+ utils.EmptyString,
+ ))
+ if err != nil {
+ t.Error(err)
+ }
+ bodyExpect := map[string]interface{}{
+ "2": "*req.field2",
+ }
+ srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ var body map[string]interface{}
+ if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(body, bodyExpect) {
+ t.Errorf("Expected %q but received %q", bodyExpect, body)
+ }
+ rw.WriteHeader(http.StatusOK)
+ }))
+ defer srv.Close()
+ cgrCfg.EEsCfg().Exporters[0].ExportPath = srv.URL + "/"
+ httpEE, err := NewHTTPjsonMapEE(cgrCfg, 0, filterS, dc)
+ if err != nil {
+ t.Error(err)
+ }
+ cgrEv.Event = map[string]interface{}{
+ "test": "string",
+ }
+ cgrCfg.EEsCfg().Exporters[0].Fields = []*config.FCTemplate{
+ {
+ Path: "*exp.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("~*req.field1", utils.InfieldSep),
+ },
+ {
+ Path: "*exp.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("*req.field2", utils.InfieldSep),
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[0].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[0].ComputeFields()
+ if err := httpEE.ExportEvent(cgrEv); err != nil {
+ t.Error(err)
+ }
+}
+
func TestHttpJsonMapComposeHeader(t *testing.T) {
cgrCfg := config.NewDefaultCGRConfig()
cgrCfg.EEsCfg().Exporters[0].Type = utils.MetaHTTPjson
diff --git a/ees/httppost_test.go b/ees/httppost_test.go
index da64b71e7..f4d78d186 100644
--- a/ees/httppost_test.go
+++ b/ees/httppost_test.go
@@ -19,6 +19,9 @@ along with this program. If not, see
package ees
import (
+ "io"
+ "net/http"
+ "net/http/httptest"
"reflect"
"testing"
@@ -141,6 +144,65 @@ func TestHttpPostExportEvent(t *testing.T) {
httpPost.OnEvicted("test", "test")
}
+func TestHttpPostExportEvent2(t *testing.T) {
+ cgrCfg := config.NewDefaultCGRConfig()
+ cgrCfg.EEsCfg().Exporters[0].Type = utils.MetaHTTPPost
+ cgrEv := new(utils.CGREvent)
+ newIDb := engine.NewInternalDB(nil, nil, true)
+ newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+ filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+ dc, err := newEEMetrics(utils.FirstNonEmpty(
+ "Local",
+ utils.EmptyString,
+ ))
+ if err != nil {
+ t.Error(err)
+ }
+ // hdrExpect := map[string][]string {
+ // "Accept-Encoding": []string{"gzip"},
+ // "Content-Type": []string{"application/x-www-form-urlencoded"},
+
+ // }
+ bodyExpect := "2=%2Areq.field2"
+ srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+ body, err := io.ReadAll(r.Body)
+ if err != nil {
+ t.Error(err)
+ }
+ if strBody := string(body); strBody != bodyExpect {
+ t.Errorf("Expected %q but received %q", bodyExpect, strBody)
+ }
+ rw.WriteHeader(http.StatusOK)
+ }))
+ defer srv.Close()
+ cgrCfg.EEsCfg().Exporters[0].ExportPath = srv.URL + "/"
+ httpPost, err := NewHTTPPostEe(cgrCfg, 0, filterS, dc)
+ if err != nil {
+ t.Error(err)
+ }
+ cgrEv.Event = map[string]interface{}{
+ "test": "string",
+ }
+ cgrCfg.EEsCfg().Exporters[0].Fields = []*config.FCTemplate{
+ {
+ Path: "*exp.1", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("~*req.field1", utils.InfieldSep),
+ },
+ {
+ Path: "*exp.2", Type: utils.MetaVariable,
+ Value: config.NewRSRParsersMustCompile("*req.field2", utils.InfieldSep),
+ },
+ }
+ for _, field := range cgrCfg.EEsCfg().Exporters[0].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[0].ComputeFields()
+ if err := httpPost.ExportEvent(cgrEv); err != nil {
+ t.Error(err)
+ }
+}
+
func TestHttpPostComposeHeader(t *testing.T) {
cgrCfg := config.NewDefaultCGRConfig()
cgrCfg.EEsCfg().Exporters[0].Type = utils.MetaHTTPPost
diff --git a/ees/posterjsonmap_test.go b/ees/posterjsonmap_test.go
index 02921cbeb..6f6b290c2 100644
--- a/ees/posterjsonmap_test.go
+++ b/ees/posterjsonmap_test.go
@@ -205,5 +205,71 @@ func TestPosterJsonMapExportEvent(t *testing.T) {
if err := pstrEE.ExportEvent(cgrEv); err == nil || err.Error() != errExpect {
t.Errorf("Expected %q but received %q", errExpect, err)
}
+ //test marshal invalid input
+ cgrEv.Event = map[string]interface{}{
+ "test": make(chan int),
+ }
+ cgrCfg.EEsCfg().Exporters[0].Fields = []*config.FCTemplate{{}}
+ for _, field := range cgrCfg.EEsCfg().Exporters[0].Fields {
+ field.ComputePath()
+ }
+ cgrCfg.EEsCfg().Exporters[0].ComputeFields()
+ errExpect = "json: unsupported type: chan int"
+ if err := pstrEE.ExportEvent(cgrEv); err == nil || err.Error() != errExpect {
+ t.Errorf("Expected %q but received %q", errExpect, err)
+ }
pstrEE.OnEvicted("test", "test")
}
+
+// func TestPosterJsonMapExportEvent2(t *testing.T) {
+// cgrCfg := config.NewDefaultCGRConfig()
+// cgrCfg.EEsCfg().Exporters[0].Type = utils.MetaSQSjsonMap
+// cgrEv := new(utils.CGREvent)
+// newIDb := engine.NewInternalDB(nil, nil, true)
+// newDM := engine.NewDataManager(newIDb, cgrCfg.CacheCfg(), nil)
+// filterS := engine.NewFilterS(cgrCfg, nil, newDM)
+// dc, err := newEEMetrics(utils.FirstNonEmpty(
+// "Local",
+// utils.EmptyString,
+// ))
+// if err != nil {
+// t.Error(err)
+// }
+// srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+// defer r.Body.Close()
+// // body, err := io.ReadAll(r.Body)
+// // if err != nil {
+// // t.Error(err)
+// // }
+// // if strBody := string(body); strBody != bodyExpect {
+// // t.Errorf("Expected %q but received %q", bodyExpect, strBody)
+// // }
+// rw.WriteHeader(http.StatusOK)
+// }))
+// defer srv.Close()
+// cgrCfg.EEsCfg().Exporters[0].ExportPath = srv.URL + "/"
+// pstrEE, err := NewPosterJSONMapEE(cgrCfg, 0, filterS, dc)
+// if err != nil {
+// t.Error(err)
+// }
+// cgrEv.Event = map[string]interface{}{
+// "test": "string",
+// }
+// cgrCfg.EEsCfg().Exporters[pstrEE.cfgIdx].Fields = []*config.FCTemplate{
+// {
+// Path: "*exp.1", Type: utils.MetaVariable,
+// Value: config.NewRSRParsersMustCompile("~*req.field1", utils.InfieldSep),
+// },
+// {
+// Path: "*exp.2", Type: utils.MetaVariable,
+// Value: config.NewRSRParsersMustCompile("*req.field2", utils.InfieldSep),
+// },
+// }
+// for _, field := range cgrCfg.EEsCfg().Exporters[pstrEE.cfgIdx].Fields {
+// field.ComputePath()
+// }
+// cgrCfg.EEsCfg().Exporters[pstrEE.cfgIdx].ComputeFields()
+// if err := pstrEE.ExportEvent(cgrEv); err != nil {
+// t.Error(err)
+// }
+// }
diff --git a/ees/sql_test.go b/ees/sql_test.go
index 8f7a1d5c0..e9092732b 100644
--- a/ees/sql_test.go
+++ b/ees/sql_test.go
@@ -1,5 +1,3 @@
-// +build integration
-
/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
@@ -48,7 +46,7 @@ func TestSqlGetMetrics(t *testing.T) {
dc: dc,
}
- if rcv := sqlEe.ID(); !reflect.DeepEqual(rcv, "3") {
- t.Errorf("Expected %+v but got %+v", "3", rcv)
+ if rcv := sqlEe.GetMetrics(); !reflect.DeepEqual(rcv, sqlEe.dc) {
+ t.Errorf("Expected %+v but got %+v", utils.ToJSON(rcv), utils.ToJSON(sqlEe.dc))
}
}