1717package controllers
1818
1919import (
20+ "bufio"
2021 "context"
2122 "fmt"
2223 "log"
2324 "os"
2425 "path/filepath"
26+ "regexp"
2527 goruntime "runtime"
2628 "strings"
2729 "testing"
@@ -146,6 +148,18 @@ func getModuleRoot(dir string) (string, error) {
146148 return dir , nil
147149}
148150
151+ // mockOSRelease returns a mock parseOSRelease function for testing.
152+ // It allows tests to simulate different operating systems without filesystem access.
153+ func mockOSRelease (osID , version string ) func () (map [string ]string , error ) {
154+ return func () (map [string ]string , error ) {
155+ return map [string ]string {
156+ "ID" : osID ,
157+ "VERSION_ID" : version ,
158+ "NAME" : osID ,
159+ }, nil
160+ }
161+ }
162+
149163// setup creates a mock kubernetes cluster and client. Nodes are labeled with the minimum
150164// required NFD labels to be detected as GPU nodes by the GPU Operator. A sample
151165// ClusterPolicy resource is applied to the cluster. The ClusterPolicyController
@@ -158,8 +172,8 @@ func setup() error {
158172 boolTrue = new (bool )
159173 * boolTrue = true
160174
161- // add env for calls that we cannot mock
162- os . Setenv ( "UNIT_TEST " , "true " )
175+ // Mock parseOSRelease to avoid filesystem dependency in tests
176+ parseOSRelease = mockOSRelease ( "ubuntu " , "20.04 " )
163177
164178 s := scheme .Scheme
165179 if err := gpuv1 .AddToScheme (s ); err != nil {
@@ -1393,3 +1407,68 @@ func TestService(t *testing.T) {
13931407 })
13941408 }
13951409}
1410+
1411+ func TestParseOSReleaseFromFile (t * testing.T ) {
1412+ parseFile := func (path string ) (map [string ]string , error ) {
1413+ release := map [string ]string {}
1414+ f , err := os .Open (path )
1415+ if err != nil {
1416+ return nil , err
1417+ }
1418+ defer f .Close ()
1419+
1420+ re := regexp .MustCompile (`^(?P<key>\w+)=(?P<value>.+)` )
1421+ scanner := bufio .NewScanner (f )
1422+ for scanner .Scan () {
1423+ line := scanner .Text ()
1424+ if match := re .FindStringSubmatch (line ); match != nil {
1425+ release [match [1 ]] = strings .Trim (match [2 ], `"` )
1426+ }
1427+ }
1428+ return release , nil
1429+ }
1430+
1431+ tests := []struct {
1432+ description string
1433+ content string
1434+ expected map [string ]string
1435+ }{
1436+ {
1437+ description : "quoted values" ,
1438+ content : `NAME="Ubuntu"` + "\n " + `VERSION_ID="20.04"` ,
1439+ expected : map [string ]string {"NAME" : "Ubuntu" , "VERSION_ID" : "20.04" },
1440+ },
1441+ {
1442+ description : "unquoted values" ,
1443+ content : `NAME=Ubuntu` + "\n " + `ID=ubuntu` ,
1444+ expected : map [string ]string {"NAME" : "Ubuntu" , "ID" : "ubuntu" },
1445+ },
1446+ {
1447+ description : "mixed quoted and unquoted" ,
1448+ content : `ID="rhel"` + "\n " + `VERSION_ID=8.5` ,
1449+ expected : map [string ]string {"ID" : "rhel" , "VERSION_ID" : "8.5" },
1450+ },
1451+ {
1452+ description : "empty lines and comments" ,
1453+ content : `NAME="Ubuntu"` + "\n \n # comment\n " + `ID=ubuntu` ,
1454+ expected : map [string ]string {"NAME" : "Ubuntu" , "ID" : "ubuntu" },
1455+ },
1456+ }
1457+
1458+ tempDir := t .TempDir ()
1459+ for i , test := range tests {
1460+ testFile := filepath .Join (tempDir , fmt .Sprintf ("os-release-%d" , i ))
1461+ err := os .WriteFile (testFile , []byte (test .content ), 0644 )
1462+ require .NoError (t , err )
1463+
1464+ result , err := parseFile (testFile )
1465+ require .NoError (t , err )
1466+ require .Equal (t , test .expected , result , test .description )
1467+ }
1468+
1469+ t .Run ("file not found" , func (t * testing.T ) {
1470+ _ , err := parseFile ("/nonexistent/path" )
1471+ require .Error (t , err )
1472+ require .True (t , os .IsNotExist (err ))
1473+ })
1474+ }
0 commit comments