001/*
002 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.debug.test;
024
025import static org.junit.Assert.*;
026
027import java.lang.management.*;
028
029import com.oracle.graal.debug.*;
030
031import org.junit.*;
032
033public class DebugTimerTest {
034
035    private static final ThreadMXBean threadMXBean = Management.getThreadMXBean();
036
037    @Before
038    public void checkCapabilities() {
039        Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
040    }
041
042    /**
043     * Actively spins the current thread for at least a given number of milliseconds in such a way
044     * that timers for the current thread keep ticking over.
045     *
046     * @return the number of milliseconds actually spent spinning which is guaranteed to be >=
047     *         {@code ms}
048     */
049    private static long spin(long ms) {
050        long start = threadMXBean.getCurrentThreadCpuTime();
051        do {
052            long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000;
053            if (durationMS >= ms) {
054                return durationMS;
055            }
056        } while (true);
057    }
058
059    @Test
060    public void test1() {
061        DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, null, null, System.out);
062        try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) {
063
064            DebugTimer timerA = Debug.timer("TimerA");
065            DebugTimer timerB = Debug.timer("TimerB");
066
067            long spinA;
068            long spinB;
069
070            try (DebugCloseable a1 = timerA.start()) {
071                spinA = spin(50);
072                try (DebugCloseable b1 = timerB.start()) {
073                    spinB = spin(50);
074                }
075            }
076
077            Assert.assertTrue(timerB.getCurrentValue() < timerA.getCurrentValue());
078            if (timerA.getFlat() != null && timerB.getFlat() != null) {
079                assertTrue(spinB >= spinA || timerB.getFlat().getCurrentValue() < timerA.getFlat().getCurrentValue());
080                assertEquals(timerA.getFlat().getCurrentValue(), timerA.getCurrentValue() - timerB.getFlat().getCurrentValue(), 10D);
081            }
082        }
083    }
084
085    @Test
086    public void test2() {
087        DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, null, null, System.out);
088        try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) {
089            DebugTimer timerC = Debug.timer("TimerC");
090            try (DebugCloseable c1 = timerC.start()) {
091                spin(50);
092                try (DebugCloseable c2 = timerC.start()) {
093                    spin(50);
094                    try (DebugCloseable c3 = timerC.start()) {
095                        spin(50);
096                        try (DebugCloseable c4 = timerC.start()) {
097                            spin(50);
098                            try (DebugCloseable c5 = timerC.start()) {
099                                spin(50);
100                            }
101                        }
102                    }
103                }
104            }
105            if (timerC.getFlat() != null) {
106                assertEquals(timerC.getFlat().getCurrentValue(), timerC.getCurrentValue());
107            }
108        }
109    }
110
111    @Test
112    public void test3() {
113        DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, null, null, System.out);
114        try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) {
115
116            DebugTimer timerD = Debug.timer("TimerD");
117            DebugTimer timerE = Debug.timer("TimerE");
118
119            long spinD1;
120            long spinE;
121
122            try (DebugCloseable d1 = timerD.start()) {
123                spinD1 = spin(50);
124                try (DebugCloseable e1 = timerE.start()) {
125                    spinE = spin(50);
126                    try (DebugCloseable d2 = timerD.start()) {
127                        spin(50);
128                        try (DebugCloseable d3 = timerD.start()) {
129                            spin(50);
130                        }
131                    }
132                }
133            }
134
135            Assert.assertTrue(timerE.getCurrentValue() < timerD.getCurrentValue());
136            if (timerD.getFlat() != null && timerE.getFlat() != null) {
137                assertTrue(spinE >= spinD1 || timerE.getFlat().getCurrentValue() < timerD.getFlat().getCurrentValue());
138                assertEquals(timerD.getFlat().getCurrentValue(), timerD.getCurrentValue() - timerE.getFlat().getCurrentValue(), 10D);
139            }
140        }
141    }
142}