1717package cdi
1818
1919import (
20+ "fmt"
2021 "os"
2122 "path/filepath"
23+ "strconv"
2224 "strings"
2325 "sync"
2426 "testing"
@@ -29,6 +31,7 @@ import (
2931 oci "github.com/opencontainers/runtime-spec/specs-go"
3032 "github.com/pkg/errors"
3133 "github.com/stretchr/testify/require"
34+ "sigs.k8s.io/yaml"
3235)
3336
3437func TestNewCache (t * testing.T ) {
@@ -1633,6 +1636,215 @@ containerEdits:
16331636 }
16341637}
16351638
1639+ func TestCacheTransientSpecs (t * testing.T ) {
1640+ type testCase struct {
1641+ name string
1642+ specs []string
1643+ invalid map [int ]bool
1644+ expected [][]string
1645+ numSpecFiles []int
1646+ }
1647+ for _ , tc := range []* testCase {
1648+ {
1649+ name : "invalid spec" ,
1650+ specs : []string {
1651+ `
1652+ cdiVersion: "` + cdi .CurrentVersion + `"
1653+ kind: "vendor.comdevice"
1654+ devices:
1655+ - name: "dev1"
1656+ containerEdits:
1657+ deviceNodes:
1658+ - path: "/dev/vendor1-dev1"
1659+ type: b
1660+ major: 10
1661+ minor: 1` ,
1662+ },
1663+ invalid : map [int ]bool {
1664+ 0 : true ,
1665+ },
1666+ },
1667+ {
1668+ name : "add/remove one valid spec" ,
1669+ specs : []string {
1670+ `
1671+ cdiVersion: "` + cdi .CurrentVersion + `"
1672+ kind: "vendor.com/device"
1673+ devices:
1674+ - name: "dev1"
1675+ containerEdits:
1676+ deviceNodes:
1677+ - path: "/dev/vendor-dev1"
1678+ type: b
1679+ major: 10
1680+ minor: 1
1681+ ` ,
1682+ "-0" ,
1683+ },
1684+ expected : [][]string {
1685+ []string {
1686+ "vendor.com/device=dev1" ,
1687+ },
1688+ nil ,
1689+ },
1690+ numSpecFiles : []int {
1691+ 1 ,
1692+ 0 ,
1693+ },
1694+ },
1695+ {
1696+ name : "add/remove multiple valid specs" ,
1697+ specs : []string {
1698+ `
1699+ cdiVersion: "` + cdi .CurrentVersion + `"
1700+ kind: "vendor.com/device"
1701+ devices:
1702+ - name: "dev1"
1703+ containerEdits:
1704+ deviceNodes:
1705+ - path: "/dev/vendor-dev1"
1706+ type: b
1707+ major: 10
1708+ minor: 1
1709+ ` ,
1710+ `
1711+ cdiVersion: "` + cdi .CurrentVersion + `"
1712+ kind: "vendor.com/device"
1713+ devices:
1714+ - name: "dev2"
1715+ containerEdits:
1716+ deviceNodes:
1717+ - path: "/dev/vendor-dev2"
1718+ type: b
1719+ major: 10
1720+ minor: 2
1721+ ` ,
1722+ `
1723+ cdiVersion: "` + cdi .CurrentVersion + `"
1724+ kind: "vendor.com/device"
1725+ devices:
1726+ - name: "dev3"
1727+ containerEdits:
1728+ deviceNodes:
1729+ - path: "/dev/vendor-dev3"
1730+ type: b
1731+ major: 10
1732+ minor: 3
1733+ - name: "dev4"
1734+ containerEdits:
1735+ deviceNodes:
1736+ - path: "/dev/vendor-dev4"
1737+ type: b
1738+ major: 10
1739+ minor: 4
1740+ ` ,
1741+ "-0" ,
1742+ "-1" ,
1743+ "-2" ,
1744+ },
1745+ expected : [][]string {
1746+ []string {
1747+ "vendor.com/device=dev1" ,
1748+ },
1749+ []string {
1750+ "vendor.com/device=dev1" ,
1751+ "vendor.com/device=dev2" ,
1752+ },
1753+ []string {
1754+ "vendor.com/device=dev1" ,
1755+ "vendor.com/device=dev2" ,
1756+ "vendor.com/device=dev3" ,
1757+ "vendor.com/device=dev4" ,
1758+ },
1759+ []string {
1760+ "vendor.com/device=dev2" ,
1761+ "vendor.com/device=dev3" ,
1762+ "vendor.com/device=dev4" ,
1763+ },
1764+ []string {
1765+ "vendor.com/device=dev3" ,
1766+ "vendor.com/device=dev4" ,
1767+ },
1768+ nil ,
1769+ },
1770+ numSpecFiles : []int {
1771+ 1 ,
1772+ 2 ,
1773+ 3 ,
1774+ 2 ,
1775+ 1 ,
1776+ 0 ,
1777+ },
1778+ },
1779+ } {
1780+ t .Run (tc .name , func (t * testing.T ) {
1781+ var (
1782+ dir string
1783+ err error
1784+ cache * Cache
1785+ specFiles []os.DirEntry
1786+ specs = map [int ]string {}
1787+ )
1788+
1789+ dir , err = createSpecDirs (t , nil , nil )
1790+ require .NoError (t , err )
1791+ cache , err = NewCache (
1792+ WithSpecDirs (
1793+ filepath .Join (dir , "etc" ),
1794+ filepath .Join (dir , "run" ),
1795+ ),
1796+ WithAutoRefresh (false ),
1797+ )
1798+
1799+ require .NoError (t , err )
1800+ require .NotNil (t , cache )
1801+
1802+ for idx , data := range tc .specs {
1803+ var (
1804+ transientID string
1805+ raw * cdi.Spec
1806+ delIdx int
1807+ err error
1808+ )
1809+
1810+ if data [0 ] == '-' {
1811+ delIdx , err = strconv .Atoi (string (data [1 :]))
1812+ require .NoError (t , err )
1813+
1814+ err = cache .RemoveSpec (specs [delIdx ])
1815+ require .NoError (t , err )
1816+ } else {
1817+ err = yaml .Unmarshal ([]byte (data ), & raw )
1818+ require .NoError (t , err )
1819+
1820+ transientID = fmt .Sprintf ("id%d" , idx )
1821+ specs [idx ], err = GenerateNameForTransientSpec (raw , transientID )
1822+ if tc .invalid [idx ] {
1823+ require .NotNil (t , err )
1824+ continue
1825+ }
1826+ require .NoError (t , err )
1827+
1828+ err = cache .WriteSpec (raw , specs [idx ])
1829+ require .NoError (t , err )
1830+ }
1831+
1832+ err = cache .Refresh ()
1833+ require .NoError (t , err )
1834+
1835+ devices := cache .ListDevices ()
1836+ require .Equal (t , tc .expected [idx ], devices )
1837+
1838+ specFiles , err = os .ReadDir (
1839+ filepath .Join (dir , "run" ),
1840+ )
1841+ require .NoError (t , err )
1842+ require .Equal (t , tc .numSpecFiles [idx ], len (specFiles ))
1843+ }
1844+ })
1845+ }
1846+ }
1847+
16361848// Create and populate automatically cleaned up spec directories.
16371849func createSpecDirs (t * testing.T , etc , run map [string ]string ) (string , error ) {
16381850 return mkTestDir (t , map [string ]map [string ]string {
0 commit comments