]> git.apps.os.sepia.ceph.com Git - teuthology.git/commitdiff
teuthology/suite: create nested matrix subsets
authorPatrick Donnelly <pdonnell@redhat.com>
Fri, 14 Jan 2022 20:25:14 +0000 (15:25 -0500)
committerPatrick Donnelly <pdonnell@redhat.com>
Tue, 24 May 2022 00:31:28 +0000 (20:31 -0400)
The general idea is to allow the `%` convolution operator to also subset
the resulting matrix. This is done by specifying a number of divisions
for the subset in the `%` file. Such as:

dir/%:

    8

This commit maps a matrix index range of `[0, Subset.size())` to the
matrix it is taking a subset of, `[0, Matrix.size())`. To get full
coverage, a random number is used to specify "which" subset to use.
Contrast with the `--subset` argument to `teuthology-suite` which lets
you specify which subset.

Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
teuthology/suite/build_matrix.py
teuthology/suite/matrix.py

index 2ae78a42be9c084909a343a6409551c5bf2061ed..5de5bd17cb4c7dfcdb835f500768c7a52dbeb117 100644 (file)
@@ -33,7 +33,9 @@ def build_matrix(path, subset=None, seed=None):
 
     For a directory with a magic '%' file, we generate a result set
     for each item in the directory, and then do a product to generate
-    a result list with all combinations (A Product).
+    a result list with all combinations (A Product). If the file
+    contains an integer, it is used as the divisor for a random
+    subset.
 
     For a directory with a magic '$' file, or for a directory whose name
     ends in '$', we generate a list of all items that we will randomly
@@ -59,22 +61,13 @@ def build_matrix(path, subset=None, seed=None):
 
 
 def _get_matrix(path, subset=None):
-    mat = None
-    first = None
-    matlimit = None
-    if subset:
-        (index, outof) = subset
-        mat = _build_matrix(path, mincyclicity=outof)
-        first = (mat.size() // outof) * index
-        if index == outof or index == outof - 1:
-            matlimit = mat.size()
-        else:
-            matlimit = (mat.size() // outof) * (index + 1)
+    (which, divisions) = (0,1) if subset is None else subset
+    if divisions > 1:
+        mat = _build_matrix(path, mincyclicity=divisions)
+        mat = matrix.Subset(mat, divisions, which=which)
     else:
-        first = 0
         mat = _build_matrix(path)
-        matlimit = mat.size()
-    return mat, first, matlimit
+    return mat, 0, mat.size()
 
 
 def _build_matrix(path, mincyclicity=0, item=''):
@@ -122,19 +115,29 @@ def _build_matrix(path, mincyclicity=0, item=''):
         elif '%' in files:
             # convolve items
             files.remove('%')
+            with open(os.path.join(path, '%')) as f:
+                divisions = f.read()
+                if len(divisions) == 0:
+                    divisions = 1
+                else:
+                    divisions = int(divisions)
+                    assert divisions > 0
             submats = []
             for fn in sorted(files):
                 submat = _build_matrix(
                     os.path.join(path, fn),
-                    mincyclicity=0,
-                    item=fn)
+                    0,
+                    fn)
                 if submat is not None:
                     submats.append(submat)
             mat = matrix.Product(item, submats)
-            if mat and mat.cyclicity() < mincyclicity:
+            minc = mincyclicity * divisions
+            if mat and mat.cyclicity() < minc:
                 mat = matrix.Cycle(
-                    (mincyclicity + mat.cyclicity() - 1) // mat.cyclicity(), mat
+                    (minc + mat.cyclicity() - 1) // mat.cyclicity(), mat
                 )
+            if divisions > 1:
+                mat = matrix.Subset(mat, divisions)
             return mat
         else:
             # list items
index 055c4485232cec67f18c7812fe3e094f27d99354..e713bc443381117ce738462128af5cd1a84ab61a 100644 (file)
@@ -75,6 +75,35 @@ class Cycle(Matrix):
     def tostr(self, depth):
         return '\t'*depth + "Cycle({num}):\n".format(num=self.num) + self.mat.tostr(depth + 1)
 
+# Logically, inverse of Cycle
+class Subset(Matrix):
+    """
+    Run a matrix subset.
+    """
+    def __init__(self, mat, divisions, which=None):
+        self.mat = mat
+        self.divisions = divisions
+        if which is None:
+            self.which = random.randint(0, divisions-1)
+        else:
+            assert which < divisions
+            self.which = which
+
+    def size(self):
+        return self.mat.size() // self.divisions
+
+    def index(self, i):
+        i += self.which * self.size()
+        assert i < self.mat.size()
+        return self.mat.index(i)
+
+    def minscanlen(self):
+        return self.mat.minscanlen()
+
+    def tostr(self, depth):
+        return '\t'*depth + "Subset({num}, {index}):\n".format(num=self.num, index=self.index) + self.mat.tostr(depth + 1)
+
+
 class Base(Matrix):
     """
     Just a single item.