blob: e096be0e2d0ee70d89f6670e5a79b563f1c8398f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.statistics;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.experimental.categories.Category;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.apache.geode.CancelCriterion;
import org.apache.geode.Statistics;
import org.apache.geode.internal.statistics.platform.LinuxProcFsStatistics;
import org.apache.geode.internal.statistics.platform.LinuxSystemStats;
import org.apache.geode.test.junit.categories.StatisticsTest;
/**
* Technically a linux only test - the file handling is all mocked up so the test can run on any
* host os.
*/
@Category(StatisticsTest.class)
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("*.IntegrationTest")
@PrepareForTest(LinuxProcFsStatistics.class)
public class LinuxSystemStatsTest extends StatSamplerTestCase {
@Rule
public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private LocalStatisticsFactory statisticsFactory;
private LocalStatisticsImpl localStats;
@Before
public void setUp() throws Exception {
File testDir = this.temporaryFolder.getRoot();
assertThat(testDir.exists()).isTrue();
System.setProperty(SimpleStatSampler.ARCHIVE_FILE_NAME_PROPERTY, testDir.getAbsolutePath()
+ File.separator + SimpleStatSampler.DEFAULT_ARCHIVE_FILE_NAME);
LinuxProcFsStatistics.init();
initStats();
StatisticsTypeImpl statisticsType = (StatisticsTypeImpl) LinuxSystemStats.getType();
localStats = (LocalStatisticsImpl) getStatisticsManager()
.createStatistics(statisticsType, statisticsType.getName());
}
@After
public void tearDown() throws Exception {
StatisticsTypeFactoryImpl.clear();
if (this.statisticsFactory != null) {
this.statisticsFactory.close();
}
}
@Test
public void testFlatStealTime() throws Exception {
String[] results = {"cpu 0 0 0 0 0 0 0 0 0 0",
// add on 4 clicks 4 idle 0 steal
"cpu 0 0 0 4 0 0 0 0 0 0"};
doTest(results, 0);
}
@Test
public void test25PercentStealTime() throws Exception {
String[] results = {"cpu 0 0 0 0 0 0 0 0 0 0",
// add on 4 clicks 3 idle 1 steal
"cpu 0 0 0 3 0 0 0 1 0 0"};
doTest(results, 25);
}
@Test
public void test66PercentStealTime() throws Exception {
String[] results = {"cpu 0 0 0 0 0 0 0 0 0 0",
// add on 3 clicks 1 idle 2 steal
"cpu 0 0 0 1 0 0 0 2 0 0"};
doTest(results, 66);
}
@Test
public void test100PercentStealTime() throws Exception {
String[] results = {"cpu 0 0 0 0 0 0 0 0 0 0",
// add on 1 clicks 0 idle 1 steal
"cpu 0 0 0 0 0 0 0 1 0 0"};
doTest(results, 100);
}
private void doTest(String[] results, int expectedStatValue) throws Exception {
Answer<FileInputStream> answer = new MyStealTimeAnswer(results);
PowerMockito.whenNew(FileInputStream.class).withArguments(anyString()).thenAnswer(answer);
LinuxProcFsStatistics.refreshSystem(localStats);
LinuxProcFsStatistics.refreshSystem(localStats);
Statistics[] statistics = getStatisticsManager().findStatisticsByTextId("LinuxSystemStats");
waitForExpectedStatValue(statistics[0], "cpuSteal", expectedStatValue, 20000, 10);
}
private void initStats() {
statisticsFactory = new LocalStatisticsFactory(new CancelCriterion() {
@Override
public String cancelInProgress() {
return null;
}
@Override
public RuntimeException generateCancelledException(Throwable e) {
return null;
}
});
}
/**
* This method will allow junit to mock up how Linux reports the CPU information though a file
* called "/proc/stat". We need to create a new file for each call since each file could represent
* another phase in the mock test.
*/
private File writeStringToFile(String mockProcStatFileContents) throws IOException {
File mockFile = temporaryFolder.newFile();
FileUtils.writeStringToFile(mockFile, mockProcStatFileContents, (Charset) null);
return mockFile;
}
@Override
protected StatisticsManager getStatisticsManager() {
return this.statisticsFactory;
}
private class MyStealTimeAnswer implements Answer<FileInputStream> {
private final List<FileInputStream> results = new ArrayList<>();
private final FileInputStream bogus;
MyStealTimeAnswer(String[] samples) throws IOException {
for (String item : samples) {
results.add(new FileInputStream(writeStringToFile(item)));
}
bogus = new FileInputStream(writeStringToFile(""));
}
@Override
public FileInputStream answer(InvocationOnMock invocation) throws Throwable {
// Since we are mocking the test we can run this test on any OS.
if ("/proc/stat".equals(invocation.getArgument(0))) {
return results.remove(0);
}
return bogus;
}
}
}