// Copyright 2017 The Prometheus Authors // Licensed 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. package xfs_test import ( "log" "reflect" "strings" "testing" "github.com/prometheus/procfs" "github.com/prometheus/procfs/xfs" ) func TestParseStats(t *testing.T) { tests := []struct { name string s string fs bool stats *xfs.Stats invalid bool }{ { name: "empty file OK", }, { name: "short or empty lines and unknown labels ignored", s: "one\n\ntwo 1 2 3\n", stats: &xfs.Stats{}, }, { name: "bad uint32", s: "extent_alloc XXX", invalid: true, }, { name: "bad uint64", s: "xpc XXX", invalid: true, }, { name: "extent_alloc bad", s: "extent_alloc 1", invalid: true, }, { name: "extent_alloc OK", s: "extent_alloc 1 2 3 4", stats: &xfs.Stats{ ExtentAllocation: xfs.ExtentAllocationStats{ ExtentsAllocated: 1, BlocksAllocated: 2, ExtentsFreed: 3, BlocksFreed: 4, }, }, }, { name: "abt bad", s: "abt 1", invalid: true, }, { name: "abt OK", s: "abt 1 2 3 4", stats: &xfs.Stats{ AllocationBTree: xfs.BTreeStats{ Lookups: 1, Compares: 2, RecordsInserted: 3, RecordsDeleted: 4, }, }, }, { name: "blk_map bad", s: "blk_map 1", invalid: true, }, { name: "blk_map OK", s: "blk_map 1 2 3 4 5 6 7", stats: &xfs.Stats{ BlockMapping: xfs.BlockMappingStats{ Reads: 1, Writes: 2, Unmaps: 3, ExtentListInsertions: 4, ExtentListDeletions: 5, ExtentListLookups: 6, ExtentListCompares: 7, }, }, }, { name: "bmbt bad", s: "bmbt 1", invalid: true, }, { name: "bmbt OK", s: "bmbt 1 2 3 4", stats: &xfs.Stats{ BlockMapBTree: xfs.BTreeStats{ Lookups: 1, Compares: 2, RecordsInserted: 3, RecordsDeleted: 4, }, }, }, { name: "dir bad", s: "dir 1", invalid: true, }, { name: "dir OK", s: "dir 1 2 3 4", stats: &xfs.Stats{ DirectoryOperation: xfs.DirectoryOperationStats{ Lookups: 1, Creates: 2, Removes: 3, Getdents: 4, }, }, }, { name: "trans bad", s: "trans 1", invalid: true, }, { name: "trans OK", s: "trans 1 2 3", stats: &xfs.Stats{ Transaction: xfs.TransactionStats{ Sync: 1, Async: 2, Empty: 3, }, }, }, { name: "ig bad", s: "ig 1", invalid: true, }, { name: "ig OK", s: "ig 1 2 3 4 5 6 7", stats: &xfs.Stats{ InodeOperation: xfs.InodeOperationStats{ Attempts: 1, Found: 2, Recycle: 3, Missed: 4, Duplicate: 5, Reclaims: 6, AttributeChange: 7, }, }, }, { name: "log bad", s: "log 1", invalid: true, }, { name: "log OK", s: "log 1 2 3 4 5", stats: &xfs.Stats{ LogOperation: xfs.LogOperationStats{ Writes: 1, Blocks: 2, NoInternalBuffers: 3, Force: 4, ForceSleep: 5, }, }, }, { name: "rw bad", s: "rw 1", invalid: true, }, { name: "rw OK", s: "rw 1 2", stats: &xfs.Stats{ ReadWrite: xfs.ReadWriteStats{ Read: 1, Write: 2, }, }, }, { name: "attr bad", s: "attr 1", invalid: true, }, { name: "attr OK", s: "attr 1 2 3 4", stats: &xfs.Stats{ AttributeOperation: xfs.AttributeOperationStats{ Get: 1, Set: 2, Remove: 3, List: 4, }, }, }, { name: "icluster bad", s: "icluster 1", invalid: true, }, { name: "icluster OK", s: "icluster 1 2 3", stats: &xfs.Stats{ InodeClustering: xfs.InodeClusteringStats{ Iflush: 1, Flush: 2, FlushInode: 3, }, }, }, { name: "vnodes bad", s: "vnodes 1", invalid: true, }, { name: "vnodes (missing free) OK", s: "vnodes 1 2 3 4 5 6 7", stats: &xfs.Stats{ Vnode: xfs.VnodeStats{ Active: 1, Allocate: 2, Get: 3, Hold: 4, Release: 5, Reclaim: 6, Remove: 7, }, }, }, { name: "vnodes (with free) OK", s: "vnodes 1 2 3 4 5 6 7 8", stats: &xfs.Stats{ Vnode: xfs.VnodeStats{ Active: 1, Allocate: 2, Get: 3, Hold: 4, Release: 5, Reclaim: 6, Remove: 7, Free: 8, }, }, }, { name: "buf bad", s: "buf 1", invalid: true, }, { name: "buf OK", s: "buf 1 2 3 4 5 6 7 8 9", stats: &xfs.Stats{ Buffer: xfs.BufferStats{ Get: 1, Create: 2, GetLocked: 3, GetLockedWaited: 4, BusyLocked: 5, MissLocked: 6, PageRetries: 7, PageFound: 8, GetRead: 9, }, }, }, { name: "xpc bad", s: "xpc 1", invalid: true, }, { name: "xpc OK", s: "xpc 1 2 3", stats: &xfs.Stats{ ExtendedPrecision: xfs.ExtendedPrecisionStats{ FlushBytes: 1, WriteBytes: 2, ReadBytes: 3, }, }, }, { name: "fixtures OK", fs: true, stats: &xfs.Stats{ ExtentAllocation: xfs.ExtentAllocationStats{ ExtentsAllocated: 92447, BlocksAllocated: 97589, ExtentsFreed: 92448, BlocksFreed: 93751, }, AllocationBTree: xfs.BTreeStats{ Lookups: 0, Compares: 0, RecordsInserted: 0, RecordsDeleted: 0, }, BlockMapping: xfs.BlockMappingStats{ Reads: 1767055, Writes: 188820, Unmaps: 184891, ExtentListInsertions: 92447, ExtentListDeletions: 92448, ExtentListLookups: 2140766, ExtentListCompares: 0, }, BlockMapBTree: xfs.BTreeStats{ Lookups: 0, Compares: 0, RecordsInserted: 0, RecordsDeleted: 0, }, DirectoryOperation: xfs.DirectoryOperationStats{ Lookups: 185039, Creates: 92447, Removes: 92444, Getdents: 136422, }, Transaction: xfs.TransactionStats{ Sync: 706, Async: 944304, Empty: 0, }, InodeOperation: xfs.InodeOperationStats{ Attempts: 185045, Found: 58807, Recycle: 0, Missed: 126238, Duplicate: 0, Reclaims: 33637, AttributeChange: 22, }, LogOperation: xfs.LogOperationStats{ Writes: 2883, Blocks: 113448, NoInternalBuffers: 9, Force: 17360, ForceSleep: 739, }, ReadWrite: xfs.ReadWriteStats{ Read: 107739, Write: 94045, }, AttributeOperation: xfs.AttributeOperationStats{ Get: 4, Set: 0, Remove: 0, List: 0, }, InodeClustering: xfs.InodeClusteringStats{ Iflush: 8677, Flush: 7849, FlushInode: 135802, }, Vnode: xfs.VnodeStats{ Active: 92601, Allocate: 0, Get: 0, Hold: 0, Release: 92444, Reclaim: 92444, Remove: 92444, Free: 0, }, Buffer: xfs.BufferStats{ Get: 2666287, Create: 7122, GetLocked: 2659202, GetLockedWaited: 3599, BusyLocked: 2, MissLocked: 7085, PageRetries: 0, PageFound: 10297, GetRead: 7085, }, ExtendedPrecision: xfs.ExtendedPrecisionStats{ FlushBytes: 399724544, WriteBytes: 92823103, ReadBytes: 86219234, }, }, }, } for i, tt := range tests { t.Logf("[%02d] test %q", i, tt.name) var ( stats *xfs.Stats err error ) if tt.s != "" { stats, err = xfs.ParseStats(strings.NewReader(tt.s)) } if tt.fs { stats, err = procfs.FS("../fixtures").XFSStats() } if tt.invalid && err == nil { t.Error("expected an error, but none occurred") } if !tt.invalid && err != nil { t.Errorf("unexpected error: %v", err) } if want, have := tt.stats, stats; !reflect.DeepEqual(want, have) { log.Printf("stats: %#v", have) t.Errorf("unexpected XFS stats:\nwant:\n%v\nhave:\n%v", want, have) } } }