1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.hadoop.util; 20 21 import java.io.File; 22 import java.io.FileWriter; 23 import java.io.IOException; 24 import java.util.Random; 25 26 import junit.framework.TestCase; 27 28 import org.apache.hadoop.fs.Path; 29 import org.apache.hadoop.mapred.TaskTrackerStatus; 30 import org.junit.Test; 31 32 /** 33 * A JUnit test to test {@link LinuxResourceCalculatorPlugin} 34 * Create the fake /proc/ information and verify the parsing and calculation 35 */ 36 public class TestLinuxResourceCalculatorPlugin extends TestCase { 37 /** 38 * LinuxResourceCalculatorPlugin with a fake timer 39 */ 40 static class FakeLinuxResourceCalculatorPlugin extends 41 LinuxResourceCalculatorPlugin { 42 43 long currentTime = 0; FakeLinuxResourceCalculatorPlugin(String procfsMemFile, String procfsCpuFile, String procfsStatFile, long jiffyLengthInMillis)44 public FakeLinuxResourceCalculatorPlugin(String procfsMemFile, 45 String procfsCpuFile, 46 String procfsStatFile, 47 long jiffyLengthInMillis) { 48 super(procfsMemFile, procfsCpuFile, procfsStatFile, jiffyLengthInMillis); 49 } 50 @Override getCurrentTime()51 long getCurrentTime() { 52 return currentTime; 53 } advanceTime(long adv)54 public void advanceTime(long adv) { 55 currentTime += adv * jiffyLengthInMillis; 56 } 57 } 58 private static final FakeLinuxResourceCalculatorPlugin plugin; 59 private static String TEST_ROOT_DIR = new Path(System.getProperty( 60 "test.build.data", "/tmp")).toString().replace(' ', '+'); 61 private static final String FAKE_MEMFILE; 62 private static final String FAKE_CPUFILE; 63 private static final String FAKE_STATFILE; 64 private static final long FAKE_JIFFY_LENGTH = 10L; 65 static { 66 int randomNum = (new Random()).nextInt(1000000000); 67 FAKE_MEMFILE = TEST_ROOT_DIR + File.separator + "MEMINFO_" + randomNum; 68 FAKE_CPUFILE = TEST_ROOT_DIR + File.separator + "CPUINFO_" + randomNum; 69 FAKE_STATFILE = TEST_ROOT_DIR + File.separator + "STATINFO_" + randomNum; 70 plugin = new FakeLinuxResourceCalculatorPlugin(FAKE_MEMFILE, FAKE_CPUFILE, 71 FAKE_STATFILE, 72 FAKE_JIFFY_LENGTH); 73 } 74 static final String MEMINFO_FORMAT = 75 "MemTotal: %d kB\n" + 76 "MemFree: %d kB\n" + 77 "Buffers: 138244 kB\n" + 78 "Cached: 947780 kB\n" + 79 "SwapCached: 142880 kB\n" + 80 "Active: 3229888 kB\n" + 81 "Inactive: %d kB\n" + 82 "SwapTotal: %d kB\n" + 83 "SwapFree: %d kB\n" + 84 "Dirty: 122012 kB\n" + 85 "Writeback: 0 kB\n" + 86 "AnonPages: 2710792 kB\n" + 87 "Mapped: 24740 kB\n" + 88 "Slab: 132528 kB\n" + 89 "SReclaimable: 105096 kB\n" + 90 "SUnreclaim: 27432 kB\n" + 91 "PageTables: 11448 kB\n" + 92 "NFS_Unstable: 0 kB\n" + 93 "Bounce: 0 kB\n" + 94 "CommitLimit: 4125904 kB\n" + 95 "Committed_AS: 4143556 kB\n" + 96 "VmallocTotal: 34359738367 kB\n" + 97 "VmallocUsed: 1632 kB\n" + 98 "VmallocChunk: 34359736375 kB\n" + 99 "HugePages_Total: 0\n" + 100 "HugePages_Free: 0\n" + 101 "HugePages_Rsvd: 0\n" + 102 "Hugepagesize: 2048 kB"; 103 104 static final String CPUINFO_FORMAT = 105 "processor : %s\n" + 106 "vendor_id : AuthenticAMD\n" + 107 "cpu family : 15\n" + 108 "model : 33\n" + 109 "model name : Dual Core AMD Opteron(tm) Processor 280\n" + 110 "stepping : 2\n" + 111 "cpu MHz : %f\n" + 112 "cache size : 1024 KB\n" + 113 "physical id : 0\n" + 114 "siblings : 2\n" + 115 "core id : 0\n" + 116 "cpu cores : 2\n" + 117 "fpu : yes\n" + 118 "fpu_exception : yes\n" + 119 "cpuid level : 1\n" + 120 "wp : yes\n" + 121 "flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov " + 122 "pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm " + 123 "3dnowext 3dnow pni lahf_lm cmp_legacy\n" + 124 "bogomips : 4792.41\n" + 125 "TLB size : 1024 4K pages\n" + 126 "clflush size : 64\n" + 127 "cache_alignment : 64\n" + 128 "address sizes : 40 bits physical, 48 bits virtual\n" + 129 "power management: ts fid vid ttp"; 130 131 static final String STAT_FILE_FORMAT = 132 "cpu %d %d %d 1646495089 831319 48713 164346 0\n" + 133 "cpu0 15096055 30805 3823005 411456015 206027 13 14269 0\n" + 134 "cpu1 14760561 89890 6432036 408707910 456857 48074 130857 0\n" + 135 "cpu2 12761169 20842 3758639 413976772 98028 411 10288 0\n" + 136 "cpu3 12355207 47322 5789691 412354390 70406 213 8931 0\n" + 137 "intr 114648668 20010764 2 0 945665 2 0 0 0 0 0 0 0 4 0 0 0 0 0 0\n" + 138 "ctxt 242017731764\n" + 139 "btime 1257808753\n" + 140 "processes 26414943\n" + 141 "procs_running 1\n" + 142 "procs_blocked 0\n"; 143 144 /** 145 * Test parsing /proc/stat and /proc/cpuinfo 146 * @throws IOException 147 */ testParsingProcStatAndCpuFile()148 public void testParsingProcStatAndCpuFile() throws IOException { 149 // Write fake /proc/cpuinfo file. 150 long numProcessors = 8; 151 long cpuFrequencyKHz = 2392781; 152 String fileContent = ""; 153 for (int i = 0; i < numProcessors; i++) { 154 fileContent += String.format(CPUINFO_FORMAT, i, cpuFrequencyKHz / 1000D) + 155 "\n"; 156 } 157 File tempFile = new File(FAKE_CPUFILE); 158 tempFile.deleteOnExit(); 159 FileWriter fWriter = new FileWriter(FAKE_CPUFILE); 160 fWriter.write(fileContent); 161 fWriter.close(); 162 assertEquals(plugin.getNumProcessors(), numProcessors); 163 assertEquals(plugin.getCpuFrequency(), cpuFrequencyKHz); 164 165 // Write fake /proc/stat file. 166 long uTime = 54972994; 167 long nTime = 188860; 168 long sTime = 19803373; 169 tempFile = new File(FAKE_STATFILE); 170 tempFile.deleteOnExit(); 171 updateStatFile(uTime, nTime, sTime); 172 assertEquals(plugin.getCumulativeCpuTime(), 173 FAKE_JIFFY_LENGTH * (uTime + nTime + sTime)); 174 assertEquals(plugin.getCpuUsage(), (float)(TaskTrackerStatus.UNAVAILABLE)); 175 176 // Advance the time and sample again to test the CPU usage calculation 177 uTime += 100L; 178 plugin.advanceTime(200L); 179 updateStatFile(uTime, nTime, sTime); 180 assertEquals(plugin.getCumulativeCpuTime(), 181 FAKE_JIFFY_LENGTH * (uTime + nTime + sTime)); 182 assertEquals(plugin.getCpuUsage(), 6.25F); 183 184 // Advance the time and sample again. This time, we call getCpuUsage() only. 185 uTime += 600L; 186 plugin.advanceTime(300L); 187 updateStatFile(uTime, nTime, sTime); 188 assertEquals(plugin.getCpuUsage(), 25F); 189 190 // Advance very short period of time (one jiffy length). 191 // In this case, CPU usage should not be updated. 192 uTime += 1L; 193 plugin.advanceTime(1L); 194 updateStatFile(uTime, nTime, sTime); 195 assertEquals(plugin.getCumulativeCpuTime(), 196 FAKE_JIFFY_LENGTH * (uTime + nTime + sTime)); 197 assertEquals(plugin.getCpuUsage(), 25F); // CPU usage is not updated. 198 } 199 200 /** 201 * Write information to fake /proc/stat file 202 */ updateStatFile(long uTime, long nTime, long sTime)203 private void updateStatFile(long uTime, long nTime, long sTime) 204 throws IOException { 205 FileWriter fWriter = new FileWriter(FAKE_STATFILE); 206 fWriter.write(String.format(STAT_FILE_FORMAT, uTime, nTime, sTime)); 207 fWriter.close(); 208 } 209 210 /** 211 * Test parsing /proc/meminfo 212 * @throws IOException 213 */ testParsingProcMemFile()214 public void testParsingProcMemFile() throws IOException { 215 long memTotal = 4058864L; 216 long memFree = 99632L; 217 long inactive = 567732L; 218 long swapTotal = 2096472L; 219 long swapFree = 1818480L; 220 File tempFile = new File(FAKE_MEMFILE); 221 tempFile.deleteOnExit(); 222 FileWriter fWriter = new FileWriter(FAKE_MEMFILE); 223 fWriter.write(String.format(MEMINFO_FORMAT, 224 memTotal, memFree, inactive, swapTotal, swapFree)); 225 226 fWriter.close(); 227 assertEquals(plugin.getAvailablePhysicalMemorySize(), 228 1024L * (memFree + inactive)); 229 assertEquals(plugin.getAvailableVirtualMemorySize(), 230 1024L * (memFree + inactive + swapFree)); 231 assertEquals(plugin.getPhysicalMemorySize(), 1024L * memTotal); 232 assertEquals(plugin.getVirtualMemorySize(), 1024L * (memTotal + swapTotal)); 233 } 234 } 235