This is an automated email from the ASF dual-hosted git repository.

srijeet0406 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 2190cd2e72 Fixes Stats Summary V5 apis to respond with RFC3339 
date/time Format (#7545)
2190cd2e72 is described below

commit 2190cd2e72a738dc490c42449ef446620b627253
Author: Jagan Parthiban <[email protected]>
AuthorDate: Thu Jul 6 02:11:03 2023 +0530

    Fixes Stats Summary V5 apis to respond with RFC3339 date/time Format (#7545)
    
    * Fixes https://github.com/apache/trafficcontrol/issues/7544 Updated V5 APIs
    
    * Fixes https://github.com/apache/trafficcontrol/issues/7544 Updated 
Integration testing based on RFC3339 Format
    
    * Fixes https://github.com/apache/trafficcontrol/issues/7544 Added Unit 
test Cases wherever possible.
    
    * CHANGELOG.md Update
    
    * Documentation Update
    
    * Fixed PR review comments
    
    * Use SOH timestamp to calculate bandwidth in TM (#7539)
    
    * Added current_time_epoch_ms and changes calculation for timestamp for ms
    
    * assigning current_time_epoch_ms to result.Time in Handler
    
    * updated CHANGELOG.md
    
    * Added check for elapsedTime.
    
    * Addressed review comments.
    
    * Added prevResult check back
    
    * pointer assignment for structure.
    
    * updated cache unite test with another check.
    
    * Fixed PR review comments for 
https://github.com/apache/trafficcontrol/issues/7544
    
    * Fixed CHANGELOG.md for 
https://github.com/apache/trafficcontrol/issues/7544
    
    * Fixed CHANGELOG.md for 
https://github.com/apache/trafficcontrol/issues/7544
    
    * Fixed CHANGELOG.md for 
https://github.com/apache/trafficcontrol/issues/7544
    
    * Fixed PR review comments for 
https://github.com/apache/trafficcontrol/issues/7544
    
    * Fixed PR Review comments
    
    * Fixed CHANGELOG.md
    
    * Update stats_summary lib
    
    * Updated statessummary file
    
    * Updated unit test cases
    
    * Temp changes to check GHA
    
    * Temp changes to check GHA
    
    * revert Temp changes to check GHA
    
    * Updated CHANGELOG.md
    
    * Updated GHA failing test case for testing.
    
    * Updated GHA failing test case.
    
    ---------
    
    Co-authored-by: Rima Shah <[email protected]>
---
 CHANGELOG.md                                       |   1 +
 docs/source/api/v5/stats_summary.rst               |  16 +--
 lib/go-tc/stats_summary.go                         | 147 +++++++++++++++++++++
 traffic_ops/testing/api/v5/stats_summary_test.go   |   9 +-
 traffic_ops/testing/api/v5/traffic_control_test.go |   2 +-
 .../trafficstats/stats_summary.go                  | 107 ++++++++++++---
 .../trafficstats/stats_summary_test.go             |  78 +++++++++++
 traffic_ops/v5-client/stats_summary.go             |  10 +-
 8 files changed, 335 insertions(+), 35 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 925f4a37cb..843149f7eb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -68,6 +68,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - [#7570](https://github.com/apache/trafficcontrol/pull/7570) *Traffic Ops* 
Fixes `deliveryservice_request_comments` v5 apis to respond with `RFC3339` 
date/time Format.
 - [#7312](https://github.com/apache/trafficcontrol/issues/7312) *Docs* 
Changing docs for CDN locks for DELETE response structure v4 and v5. 
 - [#7572](https://github.com/apache/trafficcontrol/pull/7572) *Traffic Ops* 
Fixes Delivery Service Requests V5 apis docs with RFC3339 date/time Format
+- [#7544](https://github.com/apache/trafficcontrol/issues/7544) *Traffic Ops* 
Fixes stats_summary v5 apis to respond with RFC3339 date/time Format.
 - [#7542](https://github.com/apache/trafficcontrol/pull/7542) *Traffic Ops* 
Fixed `CDN Locks` documentation to reflect the correct RFC3339 timestamps.
 - [#6340](https://github.com/apache/trafficcontrol/issues/6340) *Traffic Ops* 
Fixed alert messages for POST and PUT invalidation job APIs.
 - [#7519] (https://github.com/apache/trafficcontrol/issues/7519) *Traffic Ops* 
Fixed TO API /servers/{id}/deliveryservices endpoint to responding with all 
DS's on cache that are directly assigned and inherited through topology.
diff --git a/docs/source/api/v5/stats_summary.rst 
b/docs/source/api/v5/stats_summary.rst
index 60a45ee582..5628058685 100644
--- a/docs/source/api/v5/stats_summary.rst
+++ b/docs/source/api/v5/stats_summary.rst
@@ -110,7 +110,7 @@ Summary Stats
 
 :statName:            Stat name summary stat represents
 :statValue:           Summary stat value
-:summaryTime:         Timestamp of summary, in :ref:`non-rfc-datetime`
+:summaryTime:         Timestamp of summary, in :rfc:`3339` format
 :statDate:            Date stat was taken, in ``YYYY-MM-DD`` format
 
 .. code-block:: http
@@ -134,7 +134,7 @@ Summary Stats
                        "deliveryServiceName": "all",
                        "statName": "daily_maxgbps",
                        "statValue": 5,
-                       "summaryTime": "2019-11-19 00:04:06+00",
+                       "summaryTime": "2019-11-19T03:37:33+05:30",
                        "statDate": "2019-11-19"
                },
                {
@@ -142,7 +142,7 @@ Summary Stats
                        "deliveryServiceName": "all",
                        "statName": "daily_maxgbps",
                        "statValue": 3,
-                       "summaryTime": "2019-11-18 00:04:06+00",
+                       "summaryTime": "2019-11-18T07:59:54+05:30",
                        "statDate": "2019-11-18"
                },
                {
@@ -150,7 +150,7 @@ Summary Stats
                        "deliveryServiceName": "all",
                        "statName": "daily_bytesserved",
                        "statValue": 1000,
-                       "summaryTime": "2019-11-19 00:04:06+00",
+                       "summaryTime": "2019-11-19T00:42:12+05:30",
                        "statDate": "2019-11-19"
                }
        ]}
@@ -158,7 +158,7 @@ Summary Stats
 Last Updated Summary Stat
 """""""""""""""""""""""""
 
-:summaryTime: Timestamp of the last updated summary, in :ref:`non-rfc-datetime`
+:summaryTime: Timestamp of the last updated summary, in :rfc:`3339` format
 
 .. code-block:: http
        :caption: Response Example
@@ -176,7 +176,7 @@ Last Updated Summary Stat
        Content-Length: 150
 
        { "response": {
-               "summaryTime": "2019-11-19 00:04:06+00"
+               "summaryTime": "2019-11-19T06:12:34+05:30"
        }}
 
 ``POST``
@@ -201,7 +201,7 @@ Request Structure
 
 :statName:            Stat name summary stat represents
 :statValue:           Summary stat value
-:summaryTime:         Timestamp of summary, in :ref:`non-rfc-datetime`
+:summaryTime:         Timestamp of summary, in :rfc:`3339` format
 :statDate:            Date stat was taken, in ``YYYY-MM-DD`` format
 
 .. note:: ``statName``, ``statValue`` and ``summaryTime`` are required. If 
``cdnName`` and ``deliveryServiceName`` are not given they will default to 
``all``.
@@ -222,7 +222,7 @@ Request Structure
                "deliveryServiceName": "all",
                "statName": "daily_maxgbps",
                "statValue": 10,
-               "summaryTime": "2019-12-05 00:03:57+00",
+               "summaryTime": "2019-12-05T09:55:07+05:30",
                "statDate": "2019-12-05"
        }
 
diff --git a/lib/go-tc/stats_summary.go b/lib/go-tc/stats_summary.go
index a516ae5a55..bee02eba19 100644
--- a/lib/go-tc/stats_summary.go
+++ b/lib/go-tc/stats_summary.go
@@ -23,6 +23,7 @@ import (
        "database/sql"
        "encoding/json"
        "errors"
+       "fmt"
        "time"
 
        "github.com/apache/trafficcontrol/lib/go-tc/tovalidate"
@@ -187,3 +188,149 @@ type StatsSummaryLastUpdatedAPIResponse struct {
        Response StatsSummaryLastUpdated `json:"response"`
        Alerts
 }
+
+// StatsSummaryV5 is an alias for the latest minor version for the major 
version 5.
+type StatsSummaryV5 StatsSummaryV50
+
+// StatsSummaryV50 is a summary of some kind of statistic for a CDN and/or
+// Delivery Service.
+type StatsSummaryV50 struct {
+       CDNName         *string    `json:"cdnName"  db:"cdn_name"`
+       DeliveryService *string    `json:"deliveryServiceName"  
db:"deliveryservice_name"`
+       StatName        *string    `json:"statName"  db:"stat_name"`
+       StatValue       *float64   `json:"statValue"  db:"stat_value"`
+       SummaryTime     time.Time  `json:"summaryTime"  db:"summary_time"`
+       StatDate        *time.Time `json:"statDate"  db:"stat_date"`
+}
+
+// Validate implements the
+// 
github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api.ParseValidator
+// interface.
+func (ss StatsSummaryV5) Validate(tx *sql.Tx) error {
+       errs := tovalidate.ToErrors(validation.Errors{
+               "statName":  validation.Validate(ss.StatName, 
validation.Required),
+               "statValue": validation.Validate(ss.StatValue, 
validation.Required),
+       })
+       return util.JoinErrs(errs)
+}
+
+// UnmarshalJSON implements the encoding/json.Unmarshaler interface with a
+// customized decoding to force the date format on StatDate.
+func (ss *StatsSummaryV5) UnmarshalJSON(data []byte) error {
+       type Alias StatsSummaryV5
+       resp := struct {
+               SummaryTime string  `json:"summaryTime"`
+               StatDate    *string `json:"statDate"`
+               *Alias
+       }{
+               Alias: (*Alias)(ss),
+       }
+       err := json.Unmarshal(data, &resp)
+       if err != nil {
+               return err
+       }
+       if resp.StatDate != nil {
+               statDate, err := parseTimeV5(*resp.StatDate)
+               if err != nil {
+                       return fmt.Errorf("invalid timestamp given for 
statDate: %v", err)
+               }
+               ss.StatDate = &statDate
+       }
+
+       ss.SummaryTime, err = parseTimeV5(resp.SummaryTime)
+       if err != nil {
+               return fmt.Errorf("invalid timestamp given for summaryTime: 
%v", err)
+       }
+       return nil
+}
+
+func parseTimeV5(ts string) (time.Time, error) {
+       rt, err := time.Parse(time.RFC3339, ts)
+       if err == nil {
+               return rt, err
+       }
+       return time.Parse(dateFormat, ts)
+}
+
+// MarshalJSON implements the encoding/json.Marshaler interface with a
+// customized encoding to force the date format on StatDate.
+func (ss StatsSummaryV5) MarshalJSON() ([]byte, error) {
+       type Alias StatsSummaryV5
+       resp := struct {
+               StatDate    *string `json:"statDate"`
+               SummaryTime string  `json:"summaryTime"`
+               Alias
+       }{
+               SummaryTime: ss.SummaryTime.Format(time.RFC3339),
+               Alias:       (Alias)(ss),
+       }
+       if ss.StatDate != nil {
+               resp.StatDate = util.Ptr(ss.StatDate.Format(dateFormat))
+       }
+       return json.Marshal(&resp)
+}
+
+// StatsSummaryResponseV5 is an alias for the latest minor version for the 
major version 5.
+type StatsSummaryResponseV5 StatsSummaryResponseV50
+
+// StatsSummaryResponseV50 is the structure of a response from Traffic Ops to
+// GET requests made to its /stats_summary V5 API endpoint.
+type StatsSummaryResponseV50 struct {
+       Response []StatsSummaryV5 `json:"response"`
+       Alerts
+}
+
+// StatsSummaryLastUpdatedV5 is an alias for the latest minor version for the 
major version 5.
+type StatsSummaryLastUpdatedV5 StatsSummaryLastUpdatedV50
+
+// StatsSummaryLastUpdatedV50 is the type of the `response` property of a 
response
+// from Traffic Ops to a GET request made to its /stats_summary endpoint when
+// the 'lastSummaryDate' query string parameter is passed as 'true'.
+type StatsSummaryLastUpdatedV50 struct {
+       SummaryTime *time.Time `json:"summaryTime"  db:"summary_time"`
+}
+
+// MarshalJSON implements the encoding/json.Marshaler interface with a
+// customized encoding to force the date format on SummaryTime.
+func (ss StatsSummaryLastUpdatedV5) MarshalJSON() ([]byte, error) {
+       resp := struct {
+               SummaryTime *string `json:"summaryTime"`
+       }{}
+       if ss.SummaryTime != nil {
+               resp.SummaryTime = util.Ptr(ss.SummaryTime.Format(time.RFC3339))
+       }
+       return json.Marshal(&resp)
+}
+
+// UnmarshalJSON implements the encoding/json.Unmarshaler interface with a
+// customized decoding to force the SummaryTime format.
+func (ss *StatsSummaryLastUpdatedV5) UnmarshalJSON(data []byte) error {
+       resp := struct {
+               SummaryTime *string `json:"summaryTime"`
+       }{}
+       err := json.Unmarshal(data, &resp)
+       if err != nil {
+               return err
+       }
+       if resp.SummaryTime != nil {
+               var summaryTime time.Time
+               summaryTime, err = time.Parse(time.RFC3339, *resp.SummaryTime)
+               if err == nil {
+                       ss.SummaryTime = &summaryTime
+                       return nil
+               }
+               return err
+       }
+       return nil
+}
+
+// StatsSummaryLastUpdatedAPIResponseV5 is an alias for the latest minor 
version for the major version 5.
+type StatsSummaryLastUpdatedAPIResponseV5 StatsSummaryLastUpdatedAPIResponseV50
+
+// StatsSummaryLastUpdatedAPIResponseV50 is the type of a response from Traffic
+// Ops to a request to its /stats_summary endpoint with the 'lastSummaryDate'
+// query string parameter set to 'true'.
+type StatsSummaryLastUpdatedAPIResponseV50 struct {
+       Response StatsSummaryLastUpdatedV5 `json:"response"`
+       Alerts
+}
diff --git a/traffic_ops/testing/api/v5/stats_summary_test.go 
b/traffic_ops/testing/api/v5/stats_summary_test.go
index d7525050ee..cd4a94d657 100644
--- a/traffic_ops/testing/api/v5/stats_summary_test.go
+++ b/traffic_ops/testing/api/v5/stats_summary_test.go
@@ -34,7 +34,7 @@ func TestStatsSummary(t *testing.T) {
 
        CreateTestStatsSummaries(t)
 
-       methodTests := utils.TestCase[client.Session, client.RequestOptions, 
tc.StatsSummary]{
+       methodTests := utils.TestCase[client.Session, client.RequestOptions, 
tc.StatsSummaryV5]{
                "GET": {
                        "OK when VALID request": {
                                ClientSession: TOSession,
@@ -115,7 +115,7 @@ func TestStatsSummary(t *testing.T) {
 func validateStatsSummaryFields(expectedResp map[string]interface{}) 
utils.CkReqFunc {
        return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ 
tc.Alerts, _ error) {
                assert.RequireNotNil(t, resp, "Expected Stats Summary response 
to not be nil.")
-               statsSummaryResp := resp.([]tc.StatsSummary)
+               statsSummaryResp := resp.([]tc.StatsSummaryV5)
                for field, expected := range expectedResp {
                        for _, statsSummary := range statsSummaryResp {
                                switch field {
@@ -141,9 +141,10 @@ func validateStatsSummaryFields(expectedResp 
map[string]interface{}) utils.CkReq
 func validateStatsSummaryLastUpdatedField(expectedTime time.Time) 
utils.CkReqFunc {
        return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ 
tc.Alerts, _ error) {
                assert.RequireNotNil(t, resp, "Expected StatsSummaryLastUpdated 
response to not be nil.")
-               statsSummaryLastUpdated := resp.(tc.StatsSummaryLastUpdated)
+               statsSummaryLastUpdated := resp.(tc.StatsSummaryLastUpdatedV5)
                assert.RequireNotNil(t, statsSummaryLastUpdated.SummaryTime, 
"Expected SummaryTime to not be nil.")
-               assert.Equal(t, expectedTime, 
*statsSummaryLastUpdated.SummaryTime, "Expected SummaryTime to be %v, but got 
%v", expectedTime, *statsSummaryLastUpdated.SummaryTime)
+               assert.Equal(t, true, 
expectedTime.Equal(*statsSummaryLastUpdated.SummaryTime), "Expected SummaryTime 
to be %v, but got %v", expectedTime, *statsSummaryLastUpdated.SummaryTime)
+
        }
 }
 
diff --git a/traffic_ops/testing/api/v5/traffic_control_test.go 
b/traffic_ops/testing/api/v5/traffic_control_test.go
index 59048da291..409da97887 100644
--- a/traffic_ops/testing/api/v5/traffic_control_test.go
+++ b/traffic_ops/testing/api/v5/traffic_control_test.go
@@ -51,7 +51,7 @@ type TrafficControl struct {
        ServiceCategories                                 
[]tc.ServiceCategoryV5                  `json:"serviceCategories"`
        Statuses                                          []tc.StatusNullable   
                  `json:"statuses"`
        StaticDNSEntries                                  []tc.StaticDNSEntry   
                  `json:"staticdnsentries"`
-       StatsSummaries                                    []tc.StatsSummary     
                  `json:"statsSummaries"`
+       StatsSummaries                                    []tc.StatsSummaryV5   
                  `json:"statsSummaries"`
        Tenants                                           []tc.Tenant           
                  `json:"tenants"`
        ServerCheckExtensions                             
[]tc.ServerCheckExtensionNullable       `json:"servercheck_extensions"`
        Topologies                                        []tc.Topology         
                  `json:"topologies"`
diff --git a/traffic_ops/traffic_ops_golang/trafficstats/stats_summary.go 
b/traffic_ops/traffic_ops_golang/trafficstats/stats_summary.go
index 347e7861cc..deb4c7d346 100644
--- a/traffic_ops/traffic_ops_golang/trafficstats/stats_summary.go
+++ b/traffic_ops/traffic_ops_golang/trafficstats/stats_summary.go
@@ -25,10 +25,9 @@ import (
 
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/lib/go-util"
-       "github.com/jmoiron/sqlx"
-
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
        
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+       "github.com/jmoiron/sqlx"
 )
 
 // GetStatsSummary handler for getting stats summaries
@@ -60,16 +59,31 @@ func getLastSummaryDate(w http.ResponseWriter, r 
*http.Request, inf *api.APIInfo
                return
        }
        query := selectQuery() + where + " ORDER BY summary_time DESC"
-       statsSummaries, err := queryStatsSummary(inf.Tx, query, queryValues)
+       statsSummaries, err := queryStatsSummary(inf.Tx, inf.Version.Major, 
query, queryValues)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, err)
                return
        }
-       resp := tc.StatsSummaryLastUpdated{}
-       if len(statsSummaries) >= 1 {
-               resp.SummaryTime = &statsSummaries[0].SummaryTime
+
+       if inf.Version.Major >= 5 {
+               resp := tc.StatsSummaryLastUpdatedV5{}
+               if len(statsSummaries) >= 1 {
+                       if summary, ok := 
statsSummaries[0].(tc.StatsSummaryV5); ok {
+                               resp.SummaryTime = &summary.SummaryTime
+                       }
+               }
+               api.WriteResp(w, r, resp)
+
+       } else {
+               resp := tc.StatsSummaryLastUpdated{}
+               if len(statsSummaries) >= 1 {
+                       if summary, ok := statsSummaries[0].(tc.StatsSummary); 
ok {
+                               resp.SummaryTime = &summary.SummaryTime
+                       }
+               }
+               api.WriteResp(w, r, resp)
        }
-       api.WriteResp(w, r, resp)
+
 }
 
 func getStatsSummary(w http.ResponseWriter, r *http.Request, inf *api.APIInfo) 
{
@@ -84,31 +98,90 @@ func getStatsSummary(w http.ResponseWriter, r 
*http.Request, inf *api.APIInfo) {
                return
        }
        query := selectQuery() + where + orderBy + pagination
-       statsSummaries, err := queryStatsSummary(inf.Tx, query, queryValues)
+       queryStatsSummaries, err := queryStatsSummary(inf.Tx, 
inf.Version.Major, query, queryValues)
        if err != nil {
                api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, 
nil, err)
                return
        }
 
-       api.WriteResp(w, r, statsSummaries)
+       //api.WriteResp(w, r, statsSummaries)
+
+       if inf.Version.Major >= 5 {
+               statsSummariesV5 := make([]tc.StatsSummaryV5, 
len(queryStatsSummaries))
+               for i, oldStat := range queryStatsSummaries {
+                       if summary, ok := oldStat.(tc.StatsSummaryV5); ok {
+                               newStat := tc.StatsSummaryV5{
+                                       CDNName:         summary.CDNName,
+                                       DeliveryService: 
summary.DeliveryService,
+                                       StatName:        summary.StatName,
+                                       StatValue:       summary.StatValue,
+                                       SummaryTime:     summary.SummaryTime,
+                                       StatDate:        summary.StatDate,
+                               }
+                               statsSummariesV5[i] = newStat
+                       }
+               }
+               api.WriteResp(w, r, statsSummariesV5)
+       } else {
+               statsSummaries := make([]tc.StatsSummary, 
len(queryStatsSummaries))
+               for i, oldStat := range queryStatsSummaries {
+                       if summary, ok := oldStat.(tc.StatsSummary); ok {
+                               newStat := tc.StatsSummary{
+                                       CDNName:         summary.CDNName,
+                                       DeliveryService: 
summary.DeliveryService,
+                                       StatName:        summary.StatName,
+                                       StatValue:       summary.StatValue,
+                                       SummaryTime:     summary.SummaryTime,
+                                       StatDate:        summary.StatDate,
+                               }
+                               statsSummaries[i] = newStat
+                       }
+               }
+               api.WriteResp(w, r, statsSummaries)
+       }
+
 }
 
-func queryStatsSummary(tx *sqlx.Tx, q string, queryValues 
map[string]interface{}) ([]tc.StatsSummary, error) {
+func queryStatsSummary(tx *sqlx.Tx, version uint64, q string, queryValues 
map[string]interface{}) ([]interface{}, error) {
        rows, err := tx.NamedQuery(q, queryValues)
        if err != nil {
                return nil, fmt.Errorf("querying stats summary: %v", err)
        }
        defer rows.Close()
 
-       statsSummaries := []tc.StatsSummary{}
-       for rows.Next() {
-               s := tc.StatsSummary{}
-               if err = rows.StructScan(&s); err != nil {
-                       return nil, fmt.Errorf("scanning stats summary: %v", 
err)
+       var returnStatsSummaries []interface{}
+
+       if version >= 5 {
+               var statsSummariesV5 []tc.StatsSummaryV5
+               for rows.Next() {
+                       s := tc.StatsSummaryV5{}
+                       if err = rows.StructScan(&s); err != nil {
+                               return nil, fmt.Errorf("scanning stats summary: 
%v", err)
+                       }
+                       statsSummariesV5 = append(statsSummariesV5, s)
+               }
+               returnStatsSummaries = make([]interface{}, 
len(statsSummariesV5))
+               for i, v := range statsSummariesV5 {
+                       returnStatsSummaries[i] = v
+               }
+
+       } else {
+               var statsSummaries []tc.StatsSummary
+               for rows.Next() {
+                       s := tc.StatsSummary{}
+                       if err = rows.StructScan(&s); err != nil {
+                               return nil, fmt.Errorf("scanning stats summary: 
%v", err)
+                       }
+                       statsSummaries = append(statsSummaries, s)
+               }
+
+               returnStatsSummaries = make([]interface{}, len(statsSummaries))
+               for i, v := range statsSummaries {
+                       returnStatsSummaries[i] = v
                }
-               statsSummaries = append(statsSummaries, s)
        }
-       return statsSummaries, nil
+       return returnStatsSummaries, nil
+
 }
 
 // CreateStatsSummary handler for creating stats summaries
diff --git a/traffic_ops/traffic_ops_golang/trafficstats/stats_summary_test.go 
b/traffic_ops/traffic_ops_golang/trafficstats/stats_summary_test.go
new file mode 100644
index 0000000000..45dbfa7b79
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/trafficstats/stats_summary_test.go
@@ -0,0 +1,78 @@
+package trafficstats
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+       "testing"
+       "time"
+
+       "github.com/apache/trafficcontrol/lib/go-util/assert"
+
+       "github.com/jmoiron/sqlx"
+       "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+func TestQueryStatsSummary(t *testing.T) {
+       type testStruct struct {
+               version uint64
+       }
+
+       var testData = []testStruct{
+               {4},
+               {5},
+       }
+
+       query := "SELECT cdn_name, deliveryservice_name, stat_name, stat_value, 
summary_time, stat_date FROM stats_summary"
+       queryValues := map[string]interface{}{
+               "lastSummaryDate": "true",
+       }
+
+       for i, _ := range testData {
+               mockDB, mock, err := sqlmock.New()
+               if err != nil {
+                       t.Fatalf("an error '%v' was not expected when opening a 
stub database connection", err)
+               }
+               defer mockDB.Close()
+
+               db := sqlx.NewDb(mockDB, "sqlmock")
+               defer db.Close()
+
+               mock.ExpectBegin()
+               rows := sqlmock.NewRows([]string{
+                       "cdn_name",
+                       "deliveryservice_name",
+                       "stat_name",
+                       "stat_value",
+                       "summary_time",
+                       "stat_date",
+               })
+
+               rows.AddRow("cdn1", "all", "daily_maxgbps", 5, 
time.Now().AddDate(0, 0, -5), time.Now().AddDate(0, 0, 
-5).Truncate(24*time.Hour))
+               rows.AddRow("cdn2", "all", "daily_byteserved", 1000, 
time.Now().AddDate(0, 0, -10), time.Now().AddDate(0, 0, 
-10).Truncate(24*time.Hour))
+
+               mock.ExpectQuery("SELECT cdn_name, deliveryservice_name, 
stat_name, stat_value, summary_time, stat_date FROM 
stats_summary").WithArgs().WillReturnRows(rows)
+
+               statsSummaries1, err1 := queryStatsSummary(db.MustBegin(), 
testData[i].version, query, queryValues)
+
+               assert.NoError(t, err1)
+               assert.Equal(t, len(statsSummaries1), 2)
+       }
+
+}
diff --git a/traffic_ops/v5-client/stats_summary.go 
b/traffic_ops/v5-client/stats_summary.go
index 9b8e9a683d..03b7597cff 100644
--- a/traffic_ops/v5-client/stats_summary.go
+++ b/traffic_ops/v5-client/stats_summary.go
@@ -24,8 +24,8 @@ const apiStatsSummary = "/stats_summary"
 
 // GetSummaryStats gets a list of Summary Stats with the ability to filter on
 // CDN, Delivery Service, and/or stat name.
-func (to *Session) GetSummaryStats(opts RequestOptions) 
(tc.StatsSummaryResponse, toclientlib.ReqInf, error) {
-       var resp tc.StatsSummaryResponse
+func (to *Session) GetSummaryStats(opts RequestOptions) 
(tc.StatsSummaryResponseV5, toclientlib.ReqInf, error) {
+       var resp tc.StatsSummaryResponseV5
        reqInf, err := to.get(apiStatsSummary, opts, &resp)
        return resp, reqInf, err
 }
@@ -34,19 +34,19 @@ func (to *Session) GetSummaryStats(opts RequestOptions) 
(tc.StatsSummaryResponse
 // updated.
 // If 'statName' isn't nil, the response will be limited to the stat thereby
 // named.
-func (to *Session) GetSummaryStatsLastUpdated(opts RequestOptions) 
(tc.StatsSummaryLastUpdatedAPIResponse, toclientlib.ReqInf, error) {
+func (to *Session) GetSummaryStatsLastUpdated(opts RequestOptions) 
(tc.StatsSummaryLastUpdatedAPIResponseV5, toclientlib.ReqInf, error) {
        if opts.QueryParameters == nil {
                opts.QueryParameters = url.Values{}
        }
        opts.QueryParameters.Set("lastSummaryDate", "true")
 
-       var resp tc.StatsSummaryLastUpdatedAPIResponse
+       var resp tc.StatsSummaryLastUpdatedAPIResponseV5
        reqInf, err := to.get(apiStatsSummary, opts, &resp)
        return resp, reqInf, err
 }
 
 // CreateSummaryStats creates the given Stats Summary.
-func (to *Session) CreateSummaryStats(statsSummary tc.StatsSummary, opts 
RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) {
+func (to *Session) CreateSummaryStats(statsSummary tc.StatsSummaryV5, opts 
RequestOptions) (tc.Alerts, toclientlib.ReqInf, error) {
        var alerts tc.Alerts
        reqInf, err := to.post(apiStatsSummary, opts, statsSummary, &alerts)
        return alerts, reqInf, err

Reply via email to