@@ -25,6 +25,8 @@ import (
2525 "testing"
2626 "time"
2727
28+ "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/validate"
29+ cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
2830 oci "github.com/opencontainers/runtime-spec/specs-go"
2931 "github.com/pkg/errors"
3032 "github.com/stretchr/testify/require"
@@ -1420,6 +1422,218 @@ devices:
14201422 }
14211423}
14221424
1425+ func TestCacheWriteSpec (t * testing.T ) {
1426+ type testCase struct {
1427+ name string
1428+ etc map [string ]string
1429+ invalid map [string ]bool
1430+ }
1431+ for _ , tc := range []* testCase {
1432+ {
1433+ name : "one spec file" ,
1434+ etc : map [string ]string {
1435+ "vendor1.yaml" : `
1436+ cdiVersion: "0.3.0"
1437+ kind: "vendor1.com/device"
1438+ devices:
1439+ - name: "dev1"
1440+ containerEdits:
1441+ deviceNodes:
1442+ - path: "/dev/vendor1-dev1"
1443+ type: b
1444+ major: 10
1445+ minor: 1
1446+ ` ,
1447+ },
1448+ },
1449+ {
1450+ name : "multiple spec files" ,
1451+ etc : map [string ]string {
1452+ "vendor1.yaml" : `
1453+ cdiVersion: "0.3.0"
1454+ kind: "vendor1.com/device"
1455+ devices:
1456+ - name: "dev1"
1457+ containerEdits:
1458+ deviceNodes:
1459+ - path: "/dev/vendor1-dev1"
1460+ type: b
1461+ major: 10
1462+ minor: 1
1463+ - name: "dev2"
1464+ containerEdits:
1465+ deviceNodes:
1466+ - path: "/dev/vendor1-dev2"
1467+ type: b
1468+ major: 10
1469+ minor: 2
1470+ ` ,
1471+ "vendor2.yaml" : `
1472+ cdiVersion: "0.3.0"
1473+ kind: "vendor2.com/device"
1474+ devices:
1475+ - name: "dev1"
1476+ containerEdits:
1477+ deviceNodes:
1478+ - path: "/dev/vendor2-dev1"
1479+ type: b
1480+ major: 10
1481+ minor: 1
1482+ ` ,
1483+ "vendor3.yaml" : `
1484+ cdiVersion: "0.3.0"
1485+ kind: "vendor3.com/device"
1486+ devices:
1487+ - name: "dev1"
1488+ containerEdits:
1489+ deviceNodes:
1490+ - path: "/dev/vendor3-dev1"
1491+ type: b
1492+ major: 10
1493+ minor: 1
1494+ ` ,
1495+ },
1496+ },
1497+
1498+ {
1499+ name : "multiple spec files/data, some invalid" ,
1500+ etc : map [string ]string {
1501+ "vendor1.yaml" : `
1502+ cdiVersion: "0.3.0"
1503+ kind: "vendor1.comdevice"
1504+ devices:
1505+ - name: "dev1"
1506+ containerEdits:
1507+ deviceNodes:
1508+ - path: "/dev/vendor1-dev1"
1509+ type: b
1510+ major: 10
1511+ minor: 1
1512+ - name: "dev2"
1513+ containerEdits:
1514+ deviceNodes:
1515+ - path: "/dev/vendor1-dev2"
1516+ type: b
1517+ major: 10
1518+ minor: 2
1519+ ` ,
1520+ "vendor2.yaml" : `
1521+ cdiVersion: "0.3.0"
1522+ kind: "vendor2.com/device"
1523+ devices:
1524+ - name: "dev1"
1525+ containerEdits:
1526+ deviceNodes:
1527+ - path: "/dev/vendor2-dev1"
1528+ type: b
1529+ major: 10
1530+ minor: 1
1531+ ` ,
1532+ "vendor3.yaml" : `
1533+ cdiVersion: "0.3.0"
1534+ kind: "vendor3.com/device"
1535+ containerEdits:
1536+ deviceNodes:
1537+ - path: "/dev/vendor3-dev1"
1538+ type: b
1539+ major: 10
1540+ minor: 1
1541+ ` ,
1542+ },
1543+ invalid : map [string ]bool {
1544+ "vendor1.yaml" : true ,
1545+ "vendor3.yaml" : true ,
1546+ },
1547+ },
1548+ } {
1549+ t .Run (tc .name , func (t * testing.T ) {
1550+ var (
1551+ dir string
1552+ etc map [string ]string
1553+ raw * cdi.Spec
1554+ err error
1555+ cache * Cache
1556+ other * Cache
1557+ )
1558+
1559+ SetSpecValidator (validate .WithNamedSchema ("builtin" ))
1560+
1561+ if len (tc .invalid ) != 0 {
1562+ dir , err = createSpecDirs (t , nil , nil )
1563+ require .NoError (t , err )
1564+ cache , err = NewCache (
1565+ WithSpecDirs (
1566+ filepath .Join (dir , "etc" ),
1567+ filepath .Join (dir , "run" ),
1568+ ),
1569+ WithAutoRefresh (false ),
1570+ )
1571+
1572+ require .NoError (t , err )
1573+ require .NotNil (t , cache )
1574+
1575+ etc = map [string ]string {}
1576+ for name , data := range tc .etc {
1577+ raw , err = ParseSpec ([]byte (data ))
1578+ require .NoError (t , err )
1579+ require .NotNil (t , raw )
1580+
1581+ err = cache .WriteSpec (raw , name )
1582+
1583+ if tc .invalid [name ] {
1584+ require .Error (t , err )
1585+ } else {
1586+ require .NoError (t , err )
1587+ etc [name ] = data
1588+ }
1589+ }
1590+ } else {
1591+ etc = tc .etc
1592+ }
1593+
1594+ dir , err = createSpecDirs (t , etc , nil )
1595+ require .NoError (t , err )
1596+
1597+ cache , err = NewCache (
1598+ WithSpecDirs (
1599+ filepath .Join (dir , "etc" ),
1600+ ),
1601+ )
1602+ require .NoError (t , err )
1603+ require .NotNil (t , cache )
1604+
1605+ other , err = NewCache (
1606+ WithSpecDirs (
1607+ filepath .Join (dir , "run" ),
1608+ ),
1609+ WithAutoRefresh (false ),
1610+ )
1611+ require .NoError (t , err )
1612+ require .NotNil (t , other )
1613+
1614+ cSpecs := map [string ]* cdi.Spec {}
1615+ for _ , vendor := range cache .ListVendors () {
1616+ for _ , spec := range cache .GetVendorSpecs (vendor ) {
1617+ name := filepath .Base (spec .GetPath ())
1618+ cSpecs [name ] = spec .Spec
1619+ err = other .WriteSpec (spec .Spec , name )
1620+ require .NoError (t , err )
1621+ }
1622+ }
1623+
1624+ err = other .Refresh ()
1625+ require .NoError (t , err )
1626+
1627+ for _ , vendor := range other .ListVendors () {
1628+ for _ , spec := range other .GetVendorSpecs (vendor ) {
1629+ name := filepath .Base (spec .GetPath ())
1630+ require .Equal (t , spec .Spec , cSpecs [name ])
1631+ }
1632+ }
1633+ })
1634+ }
1635+ }
1636+
14231637// Create and populate automatically cleaned up spec directories.
14241638func createSpecDirs (t * testing.T , etc , run map [string ]string ) (string , error ) {
14251639 return mkTestDir (t , map [string ]map [string ]string {
0 commit comments