1 /*
   2  * Copyright (c) 2020, Red Hat Inc.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 import static org.junit.Assert.assertEquals;
  26 import static org.junit.Assert.assertNull;
  27 import static org.junit.Assert.assertTrue;
  28 
  29 import java.io.IOException;
  30 import java.nio.charset.StandardCharsets;
  31 import java.nio.file.Files;
  32 import java.nio.file.Path;
  33 import java.nio.file.Paths;
  34 import java.util.Arrays;
  35 
  36 import org.junit.After;
  37 import org.junit.Before;
  38 import org.junit.Test;
  39 
  40 import jdk.internal.platform.CgroupSubsystemController;
  41 import jdk.test.lib.Utils;
  42 import jdk.test.lib.util.FileUtils;
  43 
  44 /*
  45  * @test
  46  * @requires os.family == "linux"
  47  * @modules java.base/jdk.internal.platform
  48  * @library /test/lib
  49  * @run junit/othervm TestCgroupSubsystemController
  50  */
  51 
  52 /**
  53  *
  54  * Basic unit test for CgroupSubsystemController
  55  *
  56  */
  57 public class TestCgroupSubsystemController {
  58 
  59     private static final double DELTA = 0.01;
  60     private Path existingDirectory;
  61     private Path existingFile;
  62     private String existingFileName = "test-controller-file";
  63     private String existingFileContents = "foobar";
  64     private String doubleValueContents = "1.5";
  65     private String longValueContents = "3000000000";
  66     private String longValueMatchingLineContents = "testme\n" +
  67                                                    "itemfoo 25";
  68     private String longEntryContents = "s 1\n" +
  69                                        "t 2";
  70     private String longEntryName = "longEntry";
  71     private String longEntryMatchingLineName = "longMatchingLine";
  72     private String doubleValueName = "doubleValue";
  73     private String longValueName = "longValue";
  74     private CgroupSubsystemController mockController;
  75 
  76     @Before
  77     public void setup() {
  78         try {
  79             existingDirectory = Utils.createTempDirectory(TestCgroupSubsystemController.class.getSimpleName());
  80             existingFile = Paths.get(existingDirectory.toString(), existingFileName);
  81             Files.writeString(existingFile, existingFileContents, StandardCharsets.UTF_8);
  82             Path longFile = Paths.get(existingDirectory.toString(), longValueName);
  83             Files.writeString(longFile, longValueContents);
  84             Path doubleFile = Paths.get(existingDirectory.toString(), doubleValueName);
  85             Files.writeString(doubleFile, doubleValueContents);
  86             Path longEntryFile = Paths.get(existingDirectory.toString(), longEntryName);
  87             Files.writeString(longEntryFile, longEntryContents);
  88             Path longMatchingLine = Paths.get(existingDirectory.toString(), longEntryMatchingLineName);
  89             Files.writeString(longMatchingLine, longValueMatchingLineContents);
  90             mockController = new MockCgroupSubsystemController(existingDirectory.toString());
  91         } catch (IOException e) {
  92             throw new RuntimeException(e);
  93         }
  94     }
  95 
  96     @After
  97     public void teardown() {
  98         try {
  99             FileUtils.deleteFileTreeWithRetry(existingDirectory);
 100         } catch (IOException e) {
 101             System.err.println("Teardown failed. " + e.getMessage());
 102         }
 103     }
 104 
 105     @Test
 106     public void getStringValueNullController() {
 107         String val = CgroupSubsystemController.getStringValue(null, "ignore");
 108         assertNull(val);
 109     }
 110 
 111     @Test
 112     public void getStringValueIOException() throws IOException {
 113         String val = CgroupSubsystemController.getStringValue(mockController, "don-t-exist.txt");
 114         assertNull(val);
 115     }
 116 
 117     @Test
 118     public void getStringValueSuccess() {
 119         String actual = CgroupSubsystemController.getStringValue(mockController, existingFileName);
 120         assertEquals(existingFileContents, actual);
 121     }
 122 
 123     @Test
 124     public void convertStringToLong() {
 125         String strVal = "1230";
 126         long longVal = Long.parseLong(strVal);
 127         long actual = CgroupSubsystemController.convertStringToLong(strVal, -1L, 0);
 128         assertEquals(longVal, actual);
 129 
 130         String overflowVal = "9223372036854775808"; // Long.MAX_VALUE + 1
 131         long overflowDefault = -1;
 132         actual = CgroupSubsystemController.convertStringToLong(overflowVal, overflowDefault, 0);
 133         assertEquals(overflowDefault, actual);
 134         overflowDefault = Long.MAX_VALUE;
 135         actual = CgroupSubsystemController.convertStringToLong(overflowVal, overflowDefault, 0);
 136         assertEquals(overflowDefault, actual);
 137     }
 138 
 139     @Test
 140     public void convertStringRangeToIntArray() {
 141         assertNull(CgroupSubsystemController.stringRangeToIntArray(null));
 142         assertNull(CgroupSubsystemController.stringRangeToIntArray(""));
 143         String strRange = "2,4,6";
 144         int[] actual = CgroupSubsystemController.stringRangeToIntArray(strRange);
 145         int[] expected = new int[] { 2, 4, 6 };
 146         assertTrue(Arrays.equals(expected, actual));
 147         strRange = "6,1-3";
 148         actual = CgroupSubsystemController.stringRangeToIntArray(strRange);
 149         expected = new int[] { 1, 2, 3, 6 };
 150         assertTrue(Arrays.equals(expected, actual));
 151     }
 152 
 153     @Test
 154     public void getDoubleValue() {
 155         double defaultValue = -3;
 156         double actual = CgroupSubsystemController.getDoubleValue(null, null, defaultValue);
 157         assertEquals(defaultValue, actual, DELTA);
 158         double expected = Double.parseDouble(doubleValueContents);
 159         actual = CgroupSubsystemController.getDoubleValue(mockController, doubleValueName, defaultValue);
 160         assertEquals(expected, actual, DELTA);
 161         actual = CgroupSubsystemController.getDoubleValue(mockController, "don't-exist", defaultValue);
 162         assertEquals(defaultValue, actual, DELTA);
 163     }
 164 
 165     @Test
 166     public void getLongValue() {
 167         long defaultValue = -4;
 168         long actual = CgroupSubsystemController.getLongValue(null, null, Long::parseLong, defaultValue);
 169         assertEquals(defaultValue, actual);
 170         actual = CgroupSubsystemController.getLongValue(mockController, "dont-exist", Long::parseLong, defaultValue);
 171         assertEquals(defaultValue, actual);
 172         long expected = Long.parseLong(longValueContents);
 173         actual = CgroupSubsystemController.getLongValue(mockController, longValueName, Long::parseLong, defaultValue);
 174         assertEquals(expected, actual);
 175     }
 176 
 177     @Test
 178     public void getLongEntry() {
 179         long defaultValue = -5;
 180         long actual = CgroupSubsystemController.getLongEntry(null, null, "no-matter", defaultValue);
 181         assertEquals(defaultValue, actual);
 182         actual = CgroupSubsystemController.getLongEntry(mockController, "dont-exist", "foo-bar", defaultValue);
 183         assertEquals(defaultValue, actual);
 184         actual = CgroupSubsystemController.getLongEntry(mockController, longEntryName, "t", defaultValue);
 185         assertEquals(2, actual);
 186     }
 187 
 188     @Test
 189     public void getLongMatchingLine() {
 190         long defaultValue = -6;
 191         long actual = CgroupSubsystemController.getLongValueMatchingLine(null, null, "no-matter", Long::parseLong, defaultValue);
 192         assertEquals(defaultValue, actual);
 193         actual = CgroupSubsystemController.getLongValueMatchingLine(mockController, "dont-exist", "no-matter", Long::parseLong, defaultValue);
 194         assertEquals(defaultValue, actual);
 195         actual = CgroupSubsystemController.getLongValueMatchingLine(mockController, longEntryMatchingLineName, "item", TestCgroupSubsystemController::convertLong, defaultValue);
 196         assertEquals(25, actual);
 197     }
 198 
 199     public static long convertLong(String line) {
 200         return Long.parseLong(line.split("\\s+")[1]);
 201     }
 202 
 203     static class MockCgroupSubsystemController implements CgroupSubsystemController {
 204 
 205         private final String path;
 206 
 207         public MockCgroupSubsystemController(String path) {
 208             this.path = path;
 209         }
 210 
 211         @Override
 212         public String path() {
 213             return path;
 214         }
 215 
 216     }
 217 
 218 }