Skip to content

Commit 1498c54

Browse files
committed
adds Usage stats
1 parent 4f39cff commit 1498c54

File tree

4 files changed

+316
-0
lines changed

4 files changed

+316
-0
lines changed

go.mod

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
module github.com/maa3x/ppath
22

33
go 1.23.2
4+
5+
require github.com/shirou/gopsutil/v4 v4.24.12
6+
7+
require (
8+
github.com/ebitengine/purego v0.8.1 // indirect
9+
github.com/go-ole/go-ole v1.3.0 // indirect
10+
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
11+
github.com/yusufpapurcu/wmi v1.2.4 // indirect
12+
golang.org/x/sys v0.29.0 // indirect
13+
)

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
2+
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
3+
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
4+
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
5+
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
6+
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
7+
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
8+
github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4=
9+
github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o=
10+
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
11+
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
12+
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
13+
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
14+
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
15+
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
16+
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

path.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"path/filepath"
1616
"runtime"
1717
"strings"
18+
19+
"github.com/shirou/gopsutil/v4/disk"
1820
)
1921

2022
type Path string
@@ -565,6 +567,27 @@ func (p Path) SHA256() string {
565567
return p.hashFile(sha256.New())
566568
}
567569

570+
type Usage struct {
571+
Total uint64
572+
Used uint64
573+
Free uint64
574+
UsedPercent float64
575+
}
576+
577+
func (p Path) Usage() (u Usage, err error) {
578+
var s *disk.UsageStat
579+
if s, err = disk.Usage(string(p)); err != nil {
580+
return Usage{}, err
581+
}
582+
583+
return Usage{
584+
Total: s.Total,
585+
Used: s.Used,
586+
Free: s.Free,
587+
UsedPercent: s.UsedPercent,
588+
}, nil
589+
}
590+
568591
func toString(v any) string {
569592
if v == nil {
570593
return ""

path_test.go

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package ppath
22

33
import (
4+
"crypto/md5"
5+
"crypto/sha1"
6+
"crypto/sha256"
7+
"encoding/hex"
48
"io/fs"
59
"log"
610
"os"
@@ -1059,3 +1063,266 @@ func TestCreate(t *testing.T) {
10591063
}
10601064
})
10611065
}
1066+
1067+
func TestUsage(t *testing.T) {
1068+
// Test Usage on an existing directory
1069+
t.Run("ExistingDirectory", func(t *testing.T) {
1070+
p := New(".")
1071+
usage, err := p.Usage()
1072+
if err != nil {
1073+
t.Fatalf("Usage: %v", err)
1074+
}
1075+
if usage.Total == 0 {
1076+
t.Errorf("expected non-zero total usage")
1077+
}
1078+
if usage.Free == 0 {
1079+
t.Errorf("expected non-zero free usage")
1080+
}
1081+
if usage.Used == 0 {
1082+
t.Errorf("expected non-zero used usage")
1083+
}
1084+
if usage.UsedPercent == 0 {
1085+
t.Errorf("expected non-zero used percent")
1086+
}
1087+
})
1088+
1089+
// Test Usage on a non-existent path
1090+
t.Run("NonExistentPath", func(t *testing.T) {
1091+
p := New("nonexistentpath")
1092+
_, err := p.Usage()
1093+
if err == nil {
1094+
t.Errorf("expected error, got nil")
1095+
}
1096+
})
1097+
}
1098+
1099+
func TestSHA256(t *testing.T) {
1100+
p := New("testfile.txt")
1101+
defer p.Delete()
1102+
1103+
// Write test content to the file
1104+
if err := p.WriteFile(testContent); err != nil {
1105+
t.Fatalf("WriteFile: %v", err)
1106+
}
1107+
1108+
// Calculate the expected SHA256 hash
1109+
expectedHash := sha256.Sum256(testContent)
1110+
expectedHashStr := hex.EncodeToString(expectedHash[:])
1111+
1112+
// Get the SHA256 hash from the method
1113+
hashStr := p.SHA256()
1114+
1115+
if hashStr != expectedHashStr {
1116+
t.Errorf("expected %s, got %s", expectedHashStr, hashStr)
1117+
}
1118+
}
1119+
1120+
func TestSHA1(t *testing.T) {
1121+
p := New("testfile.txt")
1122+
defer p.Delete()
1123+
1124+
// Write test content to the file
1125+
if err := p.WriteFile(testContent); err != nil {
1126+
t.Fatalf("WriteFile: %v", err)
1127+
}
1128+
1129+
// Calculate the expected SHA1 hash
1130+
expectedHash := sha1.Sum(testContent)
1131+
expectedHashStr := hex.EncodeToString(expectedHash[:])
1132+
1133+
// Get the SHA1 hash from the method
1134+
hashStr := p.SHA1()
1135+
1136+
if hashStr != expectedHashStr {
1137+
t.Errorf("expected %s, got %s", expectedHashStr, hashStr)
1138+
}
1139+
}
1140+
1141+
func TestMD5(t *testing.T) {
1142+
p := New("testfile.txt")
1143+
defer p.Delete()
1144+
1145+
// Write test content to the file
1146+
if err := p.WriteFile(testContent); err != nil {
1147+
t.Fatalf("WriteFile: %v", err)
1148+
}
1149+
1150+
// Calculate the expected MD5 hash
1151+
expectedHash := md5.Sum(testContent)
1152+
expectedHashStr := hex.EncodeToString(expectedHash[:])
1153+
1154+
// Get the MD5 hash from the method
1155+
hashStr := p.MD5()
1156+
1157+
if hashStr != expectedHashStr {
1158+
t.Errorf("expected %s, got %s", expectedHashStr, hashStr)
1159+
}
1160+
}
1161+
1162+
func TestQueryHas(t *testing.T) {
1163+
tests := []struct {
1164+
path Path
1165+
key string
1166+
expected bool
1167+
}{
1168+
{New("/example/path/for/test?foo=bar"), "foo", true},
1169+
{New("/example/path/for/test?foo=bar&baz=qux"), "baz", true},
1170+
{New("/example/path/for/test?foo=bar&baz=qux"), "quux", false},
1171+
{New("/example/path/for/test"), "foo", false},
1172+
{New("/example/path/for/test?foo="), "foo", true},
1173+
}
1174+
1175+
for _, test := range tests {
1176+
result := test.path.QueryHas(test.key)
1177+
if result != test.expected {
1178+
t.Errorf("expected %v, got %v for path %s and key %s", test.expected, result, test.path, test.key)
1179+
}
1180+
}
1181+
}
1182+
1183+
func TestQueryDel(t *testing.T) {
1184+
tests := []struct {
1185+
path Path
1186+
key string
1187+
expected string
1188+
}{
1189+
{New("/example/path/for/test?foo=bar"), "foo", "/example/path/for/test"},
1190+
{New("/example/path/for/test?foo=bar&baz=qux"), "foo", "/example/path/for/test?baz=qux"},
1191+
{New("/example/path/for/test?foo=bar&baz=qux"), "baz", "/example/path/for/test?foo=bar"},
1192+
{New("/example/path/for/test?foo=bar&baz=qux"), "quux", "/example/path/for/test?baz=qux&foo=bar"},
1193+
{New("/example/path/for/test"), "foo", "/example/path/for/test"},
1194+
{New("/example/path/for/test?foo="), "foo", "/example/path/for/test"},
1195+
}
1196+
1197+
for _, test := range tests {
1198+
result := test.path.QueryDel(test.key)
1199+
if result.String() != test.expected {
1200+
t.Errorf("expected %s, got %s for path %s and key %s", test.expected, result.String(), test.path, test.key)
1201+
}
1202+
}
1203+
}
1204+
1205+
func TestQueryAdd(t *testing.T) {
1206+
tests := []struct {
1207+
path Path
1208+
key string
1209+
value any
1210+
expected string
1211+
}{
1212+
{New("/example/path/for/test"), "foo", "bar", "/example/path/for/test?foo=bar"},
1213+
{New("/example/path/for/test?foo=bar"), "baz", "qux", "/example/path/for/test?foo=bar&baz=qux"},
1214+
{New("/example/path/for/test?foo=bar"), "foo", "baz", "/example/path/for/test?foo=bar&foo=baz"},
1215+
{New("/example/path/for/test"), "foo", 123, "/example/path/for/test?foo=123"},
1216+
{New("/example/path/for/test?foo=bar"), "baz", true, "/example/path/for/test?foo=bar&baz=true"},
1217+
}
1218+
1219+
for _, test := range tests {
1220+
result := test.path.QueryAdd(test.key, test.value)
1221+
if result.String() != test.expected {
1222+
t.Errorf("expected %s, got %s for path %s, key %s, and value %v", test.expected, result.String(), test.path, test.key, test.value)
1223+
}
1224+
}
1225+
}
1226+
1227+
func TestQuerySet(t *testing.T) {
1228+
tests := []struct {
1229+
path Path
1230+
key string
1231+
value any
1232+
expected string
1233+
}{
1234+
{New("/example/path/for/test"), "foo", "bar", "/example/path/for/test?foo=bar"},
1235+
{New("/example/path/for/test?foo=bar"), "baz", "qux", "/example/path/for/test?foo=bar&baz=qux"},
1236+
{New("/example/path/for/test?foo=bar"), "foo", "baz", "/example/path/for/test?foo=baz"},
1237+
{New("/example/path/for/test"), "foo", 123, "/example/path/for/test?foo=123"},
1238+
{New("/example/path/for/test?foo=bar"), "baz", true, "/example/path/for/test?foo=bar&baz=true"},
1239+
}
1240+
1241+
for _, test := range tests {
1242+
result := test.path.QuerySet(test.key, test.value)
1243+
if result.String() != test.expected {
1244+
t.Errorf("expected %s, got %s for path %s, key %s, and value %v", test.expected, result.String(), test.path, test.key, test.value)
1245+
}
1246+
}
1247+
}
1248+
1249+
func TestQuery(t *testing.T) {
1250+
tests := []struct {
1251+
path Path
1252+
expected string
1253+
}{
1254+
{New("/example/path/for/test?foo=bar"), "foo=bar"},
1255+
{New("/example/path/for/test?foo=bar&baz=qux"), "foo=bar&baz=qux"},
1256+
{New("/example/path/for/test"), ""},
1257+
{New("/example/path/for/test?"), ""},
1258+
{New("/example/path/for/test?foo="), "foo="},
1259+
}
1260+
1261+
for _, test := range tests {
1262+
result := test.path.Query()
1263+
if result != test.expected {
1264+
t.Errorf("expected %s, got %s for path %s", test.expected, result, test.path)
1265+
}
1266+
}
1267+
}
1268+
1269+
func TestWithQuery(t *testing.T) {
1270+
tests := []struct {
1271+
path Path
1272+
query string
1273+
expected string
1274+
}{
1275+
{New("/example/path/for/test"), "foo=bar", "/example/path/for/test?foo=bar"},
1276+
{New("/example/path/for/test?existing=query"), "foo=bar", "/example/path/for/test?foo=bar"},
1277+
{New("/example/path/for/test"), "", "/example/path/for/test"},
1278+
{New("/example/path/for/test?existing=query"), "", "/example/path/for/test"},
1279+
{New("/example/path/for/test"), "foo=bar&baz=qux", "/example/path/for/test?foo=bar&baz=qux"},
1280+
}
1281+
1282+
for _, test := range tests {
1283+
result := test.path.WithQuery(test.query)
1284+
if result.String() != test.expected {
1285+
t.Errorf("expected %s, got %s for path %s and query %s", test.expected, result.String(), test.path, test.query)
1286+
}
1287+
}
1288+
}
1289+
1290+
func TestWithoutQuery(t *testing.T) {
1291+
tests := []struct {
1292+
path Path
1293+
expected string
1294+
}{
1295+
{New("/example/path/for/test?foo=bar"), "/example/path/for/test"},
1296+
{New("/example/path/for/test?foo=bar&baz=qux"), "/example/path/for/test"},
1297+
{New("/example/path/for/test"), "/example/path/for/test"},
1298+
{New("/example/path/for/test?"), "/example/path/for/test"},
1299+
{New("/example/path/for/test?foo="), "/example/path/for/test"},
1300+
}
1301+
1302+
for _, test := range tests {
1303+
result := test.path.WithoutQuery()
1304+
if result.String() != test.expected {
1305+
t.Errorf("expected %s, got %s for path %s", test.expected, result.String(), test.path)
1306+
}
1307+
}
1308+
}
1309+
1310+
func TestHasQuery(t *testing.T) {
1311+
tests := []struct {
1312+
path Path
1313+
expected bool
1314+
}{
1315+
{New("/example/path/for/test?foo=bar"), true},
1316+
{New("/example/path/for/test?foo=bar&baz=qux"), true},
1317+
{New("/example/path/for/test"), false},
1318+
{New("/example/path/for/test?"), true},
1319+
{New("/example/path/for/test?foo="), true},
1320+
}
1321+
1322+
for _, test := range tests {
1323+
result := test.path.HasQuery()
1324+
if result != test.expected {
1325+
t.Errorf("expected %v, got %v for path %s", test.expected, result, test.path)
1326+
}
1327+
}
1328+
}

0 commit comments

Comments
 (0)