github.com/galamsiva2020/kubernetes-heapster-monitoring@v0.0.0-20210823134957-3c1baa7c1e70/metrics/sources/summary/summary_test.go (about)

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package summary
    16  
    17  import (
    18  	"encoding/json"
    19  	"net"
    20  	"net/http/httptest"
    21  	"strconv"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	util "k8s.io/client-go/util/testing"
    30  	"k8s.io/heapster/metrics/core"
    31  	"k8s.io/heapster/metrics/sources/kubelet"
    32  	stats "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
    33  )
    34  
    35  const (
    36  	// Offsets from seed value in generated container stats.
    37  	offsetCPUUsageCores = iota
    38  	offsetCPUUsageCoreSeconds
    39  	offsetMemPageFaults
    40  	offsetMemMajorPageFaults
    41  	offsetMemUsageBytes
    42  	offsetMemRSSBytes
    43  	offsetMemWorkingSetBytes
    44  	offsetNetRxBytes
    45  	offsetNetRxErrors
    46  	offsetNetTxBytes
    47  	offsetNetTxErrors
    48  	offsetFsUsed
    49  	offsetFsCapacity
    50  	offsetFsAvailable
    51  	offsetAcceleratorMemoryTotal
    52  	offsetAcceleratorMemoryUsed
    53  	offsetAcceleratorDutyCycle
    54  )
    55  
    56  const (
    57  	seedNode           = 0
    58  	seedRuntime        = 100
    59  	seedKubelet        = 200
    60  	seedMisc           = 300
    61  	seedPod0           = 1000
    62  	seedPod0Container0 = 2000
    63  	seedPod0Container1 = 2001
    64  	seedPod1           = 3000
    65  	seedPod1Container  = 4000
    66  	seedPod2           = 5000
    67  	seedPod2Container0 = 6000
    68  	seedPod2Container1 = 7000
    69  	seedPod3Container0 = 9000
    70  	seedPod4           = 10000
    71  	seedPod4Container0 = 11000
    72  	seedPod5           = 12000
    73  	seedPod5Container0 = 13000
    74  )
    75  
    76  const (
    77  	namespace0 = "test0"
    78  	namespace1 = "test1"
    79  
    80  	pName0 = "pod0"
    81  	pName1 = "pod1"
    82  	pName2 = "pod0" // ensure pName2 conflicts with pName0, but is in a different namespace
    83  	pName3 = "pod2"
    84  	pName4 = "pod4" // Regression test for #1838
    85  	pName5 = "pod5"
    86  
    87  	cName00 = "c0"
    88  	cName01 = "c1"
    89  	cName10 = "c0"      // ensure cName10 conflicts with cName02, but is in a different pod
    90  	cName20 = "c1"      // ensure cName20 conflicts with cName01, but is in a different pod + namespace
    91  	cName21 = "runtime" // ensure that runtime containers are not renamed
    92  	cName30 = "c3"
    93  	cName40 = "c4" // Running, with cpu / memory stats
    94  	cName41 = "c4" // Terminated, has no CPU / Memory stats
    95  	cName42 = "c4" // Terminated, has blank CPU / Memory stats
    96  	cName50 = "c5"
    97  )
    98  
    99  var (
   100  	availableFsBytes = uint64(1130)
   101  	usedFsBytes      = uint64(13340)
   102  	totalFsBytes     = uint64(2153)
   103  	freeInode        = uint64(10440)
   104  	usedInode        = uint64(103520)
   105  	totalInode       = uint64(103620)
   106  	scrapeTime       = time.Now()
   107  	startTime        = time.Now().Add(-time.Minute)
   108  )
   109  
   110  var nodeInfo = NodeInfo{
   111  	NodeName:       "test",
   112  	HostName:       "test-hostname",
   113  	HostID:         "1234567890",
   114  	KubeletVersion: "1.2",
   115  }
   116  
   117  type fakeSource struct {
   118  	scraped bool
   119  }
   120  
   121  func (f *fakeSource) Name() string { return "fake" }
   122  func (f *fakeSource) ScrapeMetrics(start, end time.Time) (*core.DataBatch, error) {
   123  	f.scraped = true
   124  	return nil, nil
   125  }
   126  
   127  func testingSummaryMetricsSource() *summaryMetricsSource {
   128  	return &summaryMetricsSource{
   129  		node:          nodeInfo,
   130  		kubeletClient: &kubelet.KubeletClient{},
   131  	}
   132  }
   133  
   134  func TestDecodeSummaryMetrics(t *testing.T) {
   135  
   136  	ms := testingSummaryMetricsSource()
   137  	summary := stats.Summary{
   138  		Node: stats.NodeStats{
   139  			NodeName:  nodeInfo.NodeName,
   140  			StartTime: metav1.NewTime(startTime),
   141  			CPU:       genTestSummaryCPU(seedNode),
   142  			Memory:    genTestSummaryMemory(seedNode),
   143  			Network:   genTestSummaryNetwork(seedNode),
   144  			SystemContainers: []stats.ContainerStats{
   145  				genTestSummaryContainer(stats.SystemContainerKubelet, seedKubelet),
   146  				genTestSummaryContainer(stats.SystemContainerRuntime, seedRuntime),
   147  				genTestSummaryContainer(stats.SystemContainerMisc, seedMisc),
   148  			},
   149  			Fs: genTestSummaryFsStats(seedNode),
   150  		},
   151  		Pods: []stats.PodStats{{
   152  			PodRef: stats.PodReference{
   153  				Name:      pName0,
   154  				Namespace: namespace0,
   155  			},
   156  			StartTime:        metav1.NewTime(startTime),
   157  			Network:          genTestSummaryNetwork(seedPod0),
   158  			EphemeralStorage: genTestSummaryFsStats(seedPod0),
   159  			CPU:              genTestSummaryCPU(seedPod0),
   160  			Memory:           genTestSummaryMemory(seedPod0),
   161  			Containers: []stats.ContainerStats{
   162  				genTestSummaryContainer(cName00, seedPod0Container0),
   163  				genTestSummaryContainer(cName01, seedPod0Container1),
   164  				genTestSummaryTerminatedContainer(cName00, seedPod0Container0),
   165  			},
   166  		}, {
   167  			PodRef: stats.PodReference{
   168  				Name:      pName1,
   169  				Namespace: namespace0,
   170  			},
   171  			StartTime: metav1.NewTime(startTime),
   172  			Network:   genTestSummaryNetwork(seedPod1),
   173  			Containers: []stats.ContainerStats{
   174  				genTestSummaryContainer(cName10, seedPod1Container),
   175  			},
   176  			VolumeStats: []stats.VolumeStats{{
   177  				Name:    "A",
   178  				FsStats: *genTestSummaryFsStats(seedPod1),
   179  			}, {
   180  				Name:    "B",
   181  				FsStats: *genTestSummaryFsStats(seedPod1),
   182  			}},
   183  		}, {
   184  			PodRef: stats.PodReference{
   185  				Name:      pName2,
   186  				Namespace: namespace1,
   187  			},
   188  			StartTime: metav1.NewTime(startTime),
   189  			Network:   genTestSummaryNetwork(seedPod2),
   190  			Containers: []stats.ContainerStats{
   191  				genTestSummaryContainer(cName20, seedPod2Container0),
   192  				genTestSummaryContainer(cName21, seedPod2Container1),
   193  			},
   194  		}, {
   195  			PodRef: stats.PodReference{
   196  				Name:      pName3,
   197  				Namespace: namespace0,
   198  			},
   199  			Containers: []stats.ContainerStats{
   200  				genTestSummaryContainer(cName30, seedPod3Container0),
   201  			},
   202  			VolumeStats: []stats.VolumeStats{{
   203  				Name: "C",
   204  				FsStats: stats.FsStats{
   205  					AvailableBytes: &availableFsBytes,
   206  					UsedBytes:      &usedFsBytes,
   207  					CapacityBytes:  &totalFsBytes,
   208  					InodesFree:     &freeInode,
   209  					InodesUsed:     &usedInode,
   210  					Inodes:         &totalInode,
   211  				},
   212  			},
   213  			},
   214  		}, {
   215  			PodRef: stats.PodReference{
   216  				Name:      pName4,
   217  				Namespace: namespace0,
   218  			},
   219  			StartTime: metav1.NewTime(startTime),
   220  			Network:   genTestSummaryNetwork(seedPod4),
   221  			Containers: []stats.ContainerStats{
   222  				genTestSummaryContainer(cName40, seedPod4Container0),
   223  				genTestSummaryTerminatedContainerNoStats(cName41),
   224  				genTestSummaryTerminatedContainerBlankStats(cName42),
   225  			},
   226  		}, {
   227  			PodRef: stats.PodReference{
   228  				Name:      pName5,
   229  				Namespace: namespace0,
   230  			},
   231  			Network:   genTestSummaryNetwork(seedPod5),
   232  			StartTime: metav1.NewTime(startTime),
   233  			Containers: []stats.ContainerStats{
   234  				genTestSummaryContainerWithAccelerator(cName50, seedPod5Container0),
   235  			},
   236  		}},
   237  	}
   238  
   239  	containerFs := []string{"/", "logs"}
   240  	expectations := []struct {
   241  		key                       string
   242  		setType                   string
   243  		seed                      int64
   244  		cpu                       bool
   245  		memory                    bool
   246  		network                   bool
   247  		accelerators              bool
   248  		ephemeralstorage          bool
   249  		containerEphemeralstorage bool
   250  		fs                        []string
   251  	}{{
   252  		key:              core.NodeKey(nodeInfo.NodeName),
   253  		setType:          core.MetricSetTypeNode,
   254  		seed:             seedNode,
   255  		cpu:              true,
   256  		memory:           true,
   257  		network:          true,
   258  		ephemeralstorage: true,
   259  		fs:               []string{"/"},
   260  	}, {
   261  		key:     core.NodeContainerKey(nodeInfo.NodeName, "kubelet"),
   262  		setType: core.MetricSetTypeSystemContainer,
   263  		seed:    seedKubelet,
   264  		cpu:     true,
   265  		memory:  true,
   266  	}, {
   267  		key:     core.NodeContainerKey(nodeInfo.NodeName, "docker-daemon"),
   268  		setType: core.MetricSetTypeSystemContainer,
   269  		seed:    seedRuntime,
   270  		cpu:     true,
   271  		memory:  true,
   272  	}, {
   273  		key:     core.NodeContainerKey(nodeInfo.NodeName, "system"),
   274  		setType: core.MetricSetTypeSystemContainer,
   275  		seed:    seedMisc,
   276  		cpu:     true,
   277  		memory:  true,
   278  	}, {
   279  		key:              core.PodKey(namespace0, pName0),
   280  		setType:          core.MetricSetTypePod,
   281  		seed:             seedPod0,
   282  		network:          true,
   283  		cpu:              true,
   284  		memory:           true,
   285  		ephemeralstorage: true,
   286  	}, {
   287  		key:     core.PodKey(namespace0, pName1),
   288  		setType: core.MetricSetTypePod,
   289  		seed:    seedPod1,
   290  		network: true,
   291  		fs:      []string{"Volume:A", "Volume:B"},
   292  	}, {
   293  		key:     core.PodKey(namespace1, pName2),
   294  		setType: core.MetricSetTypePod,
   295  		seed:    seedPod2,
   296  		network: true,
   297  	}, {
   298  		key:     core.PodKey(namespace0, pName4),
   299  		setType: core.MetricSetTypePod,
   300  		seed:    seedPod4,
   301  		network: true,
   302  	}, {
   303  		key:     core.PodKey(namespace0, pName5),
   304  		setType: core.MetricSetTypePod,
   305  		seed:    seedPod5,
   306  		network: true,
   307  	}, {
   308  		key:                       core.PodContainerKey(namespace0, pName0, cName00),
   309  		setType:                   core.MetricSetTypePodContainer,
   310  		seed:                      seedPod0Container0,
   311  		cpu:                       true,
   312  		memory:                    true,
   313  		containerEphemeralstorage: true,
   314  		fs:                        containerFs,
   315  	}, {
   316  		key:     core.PodContainerKey(namespace0, pName0, cName01),
   317  		setType: core.MetricSetTypePodContainer,
   318  		seed:    seedPod0Container1,
   319  		cpu:     true,
   320  		memory:  true,
   321  		fs:      containerFs,
   322  	}, {
   323  		key:     core.PodContainerKey(namespace0, pName1, cName10),
   324  		setType: core.MetricSetTypePodContainer,
   325  		seed:    seedPod1Container,
   326  		cpu:     true,
   327  		memory:  true,
   328  		fs:      containerFs,
   329  	}, {
   330  		key:     core.PodContainerKey(namespace1, pName2, cName20),
   331  		setType: core.MetricSetTypePodContainer,
   332  		seed:    seedPod2Container0,
   333  		cpu:     true,
   334  		memory:  true,
   335  		fs:      containerFs,
   336  	}, {
   337  		key:     core.PodContainerKey(namespace1, pName2, cName21),
   338  		setType: core.MetricSetTypePodContainer,
   339  		seed:    seedPod2Container1,
   340  		cpu:     true,
   341  		memory:  true,
   342  		fs:      containerFs,
   343  	}, {
   344  		key:     core.PodContainerKey(namespace0, pName3, cName30),
   345  		setType: core.MetricSetTypePodContainer,
   346  		seed:    seedPod3Container0,
   347  		cpu:     true,
   348  		memory:  true,
   349  		fs:      containerFs,
   350  	}, {
   351  		key:     core.PodContainerKey(namespace0, pName4, cName40),
   352  		setType: core.MetricSetTypePodContainer,
   353  		seed:    seedPod4Container0,
   354  		cpu:     true,
   355  		memory:  true,
   356  		fs:      containerFs,
   357  	}, {
   358  		key:          core.PodContainerKey(namespace0, pName5, cName50),
   359  		setType:      core.MetricSetTypePodContainer,
   360  		seed:         seedPod5Container0,
   361  		cpu:          true,
   362  		accelerators: true,
   363  	}}
   364  
   365  	metrics := ms.decodeSummary(&summary)
   366  	for _, e := range expectations {
   367  		m, ok := metrics[e.key]
   368  		if !assert.True(t, ok, "missing metric %q", e.key) {
   369  			continue
   370  		}
   371  		assert.Equal(t, m.Labels[core.LabelMetricSetType.Key], e.setType, e.key)
   372  		assert.Equal(t, m.CollectionStartTime, startTime, e.key)
   373  		assert.Equal(t, m.ScrapeTime, scrapeTime, e.key)
   374  		if e.cpu {
   375  			checkIntMetric(t, m, e.key, core.MetricCpuUsage, e.seed+offsetCPUUsageCoreSeconds)
   376  		}
   377  		if e.memory {
   378  			checkIntMetric(t, m, e.key, core.MetricMemoryUsage, e.seed+offsetMemUsageBytes)
   379  			checkIntMetric(t, m, e.key, core.MetricMemoryWorkingSet, e.seed+offsetMemWorkingSetBytes)
   380  			checkIntMetric(t, m, e.key, core.MetricMemoryRSS, e.seed+offsetMemRSSBytes)
   381  			checkIntMetric(t, m, e.key, core.MetricMemoryPageFaults, e.seed+offsetMemPageFaults)
   382  			checkIntMetric(t, m, e.key, core.MetricMemoryMajorPageFaults, e.seed+offsetMemMajorPageFaults)
   383  		}
   384  		if e.network {
   385  			checkIntMetric(t, m, e.key, core.MetricNetworkRx, e.seed+offsetNetRxBytes)
   386  			checkIntMetric(t, m, e.key, core.MetricNetworkRxErrors, e.seed+offsetNetRxErrors)
   387  			checkIntMetric(t, m, e.key, core.MetricNetworkTx, e.seed+offsetNetTxBytes)
   388  			checkIntMetric(t, m, e.key, core.MetricNetworkTxErrors, e.seed+offsetNetTxErrors)
   389  		}
   390  		if e.accelerators {
   391  			checkAcceleratorMetric(t, m, e.key, core.MetricAcceleratorMemoryTotal, e.seed+offsetAcceleratorMemoryTotal)
   392  			checkAcceleratorMetric(t, m, e.key, core.MetricAcceleratorMemoryUsed, e.seed+offsetAcceleratorMemoryUsed)
   393  			checkAcceleratorMetric(t, m, e.key, core.MetricAcceleratorDutyCycle, e.seed+offsetAcceleratorDutyCycle)
   394  		}
   395  		if e.ephemeralstorage {
   396  			checkIntMetric(t, m, e.key, core.MetricEphemeralStorageUsage, e.seed+offsetFsUsed)
   397  		}
   398  		if e.containerEphemeralstorage {
   399  			checkIntMetric(t, m, e.key, core.MetricEphemeralStorageUsage, 2*(e.seed+offsetFsUsed))
   400  		}
   401  		for _, label := range e.fs {
   402  			checkFsMetric(t, m, e.key, label, core.MetricFilesystemAvailable, e.seed+offsetFsAvailable)
   403  			checkFsMetric(t, m, e.key, label, core.MetricFilesystemLimit, e.seed+offsetFsCapacity)
   404  			checkFsMetric(t, m, e.key, label, core.MetricFilesystemUsage, e.seed+offsetFsUsed)
   405  		}
   406  		delete(metrics, e.key)
   407  	}
   408  
   409  	// Verify volume information labeled metrics
   410  	var volumeInformationMetricsKey = core.PodKey(namespace0, pName3)
   411  	var mappedVolumeStats = map[string]int64{}
   412  	for _, labeledMetric := range metrics[volumeInformationMetricsKey].LabeledMetrics {
   413  		assert.True(t, strings.HasPrefix("Volume:C", labeledMetric.Labels["resource_id"]))
   414  		mappedVolumeStats[labeledMetric.Name] = labeledMetric.IntValue
   415  	}
   416  
   417  	assert.True(t, mappedVolumeStats["filesystem/available"] == int64(availableFsBytes))
   418  	assert.True(t, mappedVolumeStats["filesystem/usage"] == int64(usedFsBytes))
   419  	assert.True(t, mappedVolumeStats["filesystem/limit"] == int64(totalFsBytes))
   420  
   421  	delete(metrics, volumeInformationMetricsKey)
   422  
   423  	for k, v := range metrics {
   424  		assert.Fail(t, "unexpected metric", "%q: %+v", k, v)
   425  	}
   426  }
   427  
   428  func genTestSummaryTerminatedContainer(name string, seed int) stats.ContainerStats {
   429  	return stats.ContainerStats{
   430  		Name:      name,
   431  		StartTime: metav1.NewTime(startTime.Add(-time.Minute)),
   432  		CPU:       genTestSummaryZeroCPU(seed),
   433  		Memory:    genTestSummaryZeroMemory(seed),
   434  		Rootfs:    genTestSummaryFsStats(seed),
   435  		Logs:      genTestSummaryFsStats(seed),
   436  	}
   437  }
   438  
   439  func genTestSummaryTerminatedContainerNoStats(name string) stats.ContainerStats {
   440  	return stats.ContainerStats{
   441  		Name:      name,
   442  		StartTime: metav1.NewTime(startTime.Add(-time.Minute)),
   443  	}
   444  }
   445  
   446  func genTestSummaryTerminatedContainerBlankStats(name string) stats.ContainerStats {
   447  	return stats.ContainerStats{
   448  		Name:      name,
   449  		StartTime: metav1.NewTime(startTime.Add(-time.Minute)),
   450  		CPU:       genTestSummaryBlankCPU(),
   451  		Memory:    genTestSummaryBlankMemory(),
   452  	}
   453  }
   454  
   455  func genTestSummaryContainer(name string, seed int) stats.ContainerStats {
   456  	return stats.ContainerStats{
   457  		Name:      name,
   458  		StartTime: metav1.NewTime(startTime),
   459  		CPU:       genTestSummaryCPU(seed),
   460  		Memory:    genTestSummaryMemory(seed),
   461  		Rootfs:    genTestSummaryFsStats(seed),
   462  		Logs:      genTestSummaryFsStats(seed),
   463  	}
   464  }
   465  
   466  func genTestSummaryContainerWithAccelerator(name string, seed int) stats.ContainerStats {
   467  	return stats.ContainerStats{
   468  		Name:         name,
   469  		StartTime:    metav1.NewTime(startTime),
   470  		CPU:          genTestSummaryCPU(seed),
   471  		Accelerators: genTestSummaryAccelerator(seed),
   472  	}
   473  }
   474  
   475  func genTestSummaryAccelerator(seed int) []stats.AcceleratorStats {
   476  	return []stats.AcceleratorStats{
   477  		{
   478  			Make:        "nvidia",
   479  			Model:       "Tesla P100",
   480  			ID:          "GPU-deadbeef-1234-5678-90ab-feedfacecafe",
   481  			MemoryTotal: *uint64Val(seed, offsetAcceleratorMemoryTotal),
   482  			MemoryUsed:  *uint64Val(seed, offsetAcceleratorMemoryUsed),
   483  			DutyCycle:   *uint64Val(seed, offsetAcceleratorDutyCycle),
   484  		},
   485  	}
   486  }
   487  
   488  func genTestSummaryZeroCPU(seed int) *stats.CPUStats {
   489  	cpu := stats.CPUStats{
   490  		Time:                 metav1.NewTime(scrapeTime),
   491  		UsageNanoCores:       uint64Val(seed, -seed),
   492  		UsageCoreNanoSeconds: uint64Val(seed, offsetCPUUsageCoreSeconds),
   493  	}
   494  	*cpu.UsageCoreNanoSeconds *= uint64(time.Millisecond.Nanoseconds())
   495  	return &cpu
   496  }
   497  
   498  func genTestSummaryCPU(seed int) *stats.CPUStats {
   499  	cpu := stats.CPUStats{
   500  		Time:                 metav1.NewTime(scrapeTime),
   501  		UsageNanoCores:       uint64Val(seed, offsetCPUUsageCores),
   502  		UsageCoreNanoSeconds: uint64Val(seed, offsetCPUUsageCoreSeconds),
   503  	}
   504  	*cpu.UsageNanoCores *= uint64(time.Millisecond.Nanoseconds())
   505  	return &cpu
   506  }
   507  
   508  func genTestSummaryBlankCPU() *stats.CPUStats {
   509  	return &stats.CPUStats{
   510  		Time: metav1.NewTime(scrapeTime),
   511  	}
   512  }
   513  
   514  func genTestSummaryZeroMemory(seed int) *stats.MemoryStats {
   515  	return &stats.MemoryStats{
   516  		Time:            metav1.NewTime(scrapeTime),
   517  		UsageBytes:      uint64Val(seed, offsetMemUsageBytes),
   518  		WorkingSetBytes: uint64Val(seed, offsetMemWorkingSetBytes),
   519  		RSSBytes:        uint64Val(seed, -seed),
   520  		PageFaults:      uint64Val(seed, offsetMemPageFaults),
   521  		MajorPageFaults: uint64Val(seed, offsetMemMajorPageFaults),
   522  	}
   523  }
   524  
   525  func genTestSummaryMemory(seed int) *stats.MemoryStats {
   526  	return &stats.MemoryStats{
   527  		Time:            metav1.NewTime(scrapeTime),
   528  		UsageBytes:      uint64Val(seed, offsetMemUsageBytes),
   529  		WorkingSetBytes: uint64Val(seed, offsetMemWorkingSetBytes),
   530  		RSSBytes:        uint64Val(seed, offsetMemRSSBytes),
   531  		PageFaults:      uint64Val(seed, offsetMemPageFaults),
   532  		MajorPageFaults: uint64Val(seed, offsetMemMajorPageFaults),
   533  	}
   534  }
   535  
   536  func genTestSummaryBlankMemory() *stats.MemoryStats {
   537  	return &stats.MemoryStats{
   538  		Time: metav1.NewTime(scrapeTime),
   539  	}
   540  }
   541  
   542  func genTestSummaryNetwork(seed int) *stats.NetworkStats {
   543  	return &stats.NetworkStats{
   544  		Time: metav1.NewTime(scrapeTime),
   545  		InterfaceStats: stats.InterfaceStats{
   546  			RxBytes:  uint64Val(seed, offsetNetRxBytes),
   547  			RxErrors: uint64Val(seed, offsetNetRxErrors),
   548  			TxBytes:  uint64Val(seed, offsetNetTxBytes),
   549  			TxErrors: uint64Val(seed, offsetNetTxErrors),
   550  		},
   551  	}
   552  }
   553  
   554  func genTestSummaryFsStats(seed int) *stats.FsStats {
   555  	return &stats.FsStats{
   556  		AvailableBytes: uint64Val(seed, offsetFsAvailable),
   557  		CapacityBytes:  uint64Val(seed, offsetFsCapacity),
   558  		UsedBytes:      uint64Val(seed, offsetFsUsed),
   559  	}
   560  }
   561  
   562  // Convenience function for taking the address of a uint64 literal.
   563  func uint64Val(seed, offset int) *uint64 {
   564  	val := uint64(seed + offset)
   565  	return &val
   566  }
   567  
   568  func checkIntMetric(t *testing.T, metrics *core.MetricSet, key string, metric core.Metric, value int64) {
   569  	m, ok := metrics.MetricValues[metric.Name]
   570  	if !assert.True(t, ok, "missing %q:%q", key, metric.Name) {
   571  		return
   572  	}
   573  	assert.Equal(t, value, m.IntValue, "%q:%q", key, metric.Name)
   574  }
   575  
   576  func checkFsMetric(t *testing.T, metrics *core.MetricSet, key, label string, metric core.Metric, value int64) {
   577  	for _, m := range metrics.LabeledMetrics {
   578  		if m.Name == metric.Name && m.Labels[core.LabelResourceID.Key] == label {
   579  			assert.Equal(t, value, m.IntValue, "%q:%q[%s]", key, metric.Name, label)
   580  			return
   581  		}
   582  	}
   583  	assert.Fail(t, "missing filesystem metric", "%q:[%q]:%q", key, metric.Name, label)
   584  }
   585  
   586  func checkAcceleratorMetric(t *testing.T, metrics *core.MetricSet, key string, metric core.Metric, value int64) {
   587  	for _, m := range metrics.LabeledMetrics {
   588  		if m.Name == metric.Name {
   589  			assert.Equal(t, value, m.IntValue, "%q:%q", key, metric.Name)
   590  			return
   591  		}
   592  	}
   593  	assert.Fail(t, "missing accelerator metric", "%q:[%q]", key, metric.Name)
   594  }
   595  
   596  func TestScrapeSummaryMetrics(t *testing.T) {
   597  	summary := stats.Summary{
   598  		Node: stats.NodeStats{
   599  			NodeName:  nodeInfo.NodeName,
   600  			StartTime: metav1.NewTime(startTime),
   601  		},
   602  	}
   603  	data, err := json.Marshal(&summary)
   604  	require.NoError(t, err)
   605  
   606  	server := httptest.NewServer(&util.FakeHandler{
   607  		StatusCode:   200,
   608  		ResponseBody: string(data),
   609  		T:            t,
   610  	})
   611  	defer server.Close()
   612  
   613  	ms := testingSummaryMetricsSource()
   614  	split := strings.SplitN(strings.Replace(server.URL, "http://", "", 1), ":", 2)
   615  	ms.node.IP = net.ParseIP(split[0])
   616  	ms.node.Port, err = strconv.Atoi(split[1])
   617  	require.NoError(t, err)
   618  
   619  	res, err := ms.ScrapeMetrics(time.Now(), time.Now())
   620  	assert.Nil(t, err, "scrape error")
   621  	assert.Equal(t, res.MetricSets["node:test"].Labels[core.LabelMetricSetType.Key], core.MetricSetTypeNode)
   622  }