<commit_before>/*
 * 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.jackrabbit.oak.stats;

import static junit.framework.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.junit.Ignore;
import org.junit.Test;

public class ClockTest {

    /**
     * Helper for checking how accurate the system clock is.
     */
    public static void main(String[] args) {
        List<Long> values = new ArrayList<Long>();
        long end = System.currentTimeMillis() + 10000; // 10 seconds
        long last = System.currentTimeMillis();
        long current = last;

        do {
            current = System.currentTimeMillis();
            if (current != last && current != last + 1) {
                values.add(current);
            }
            last = current;
        } while (current < end);
        for (int i = 1; i < values.size(); i++) {
            System.out.println(values.get(i) + " " + (values.get(i) - values.get(i - 1)));
        }
    }

    @Test
    @Ignore("OAK-1564")  // FIXME OAK-1564 ClockTest on Windows fails
    public void testClockDrift() throws InterruptedException {
        ScheduledExecutorService executor =
                Executors.newSingleThreadScheduledExecutor();
        final long limit = 20;
        try {
            Clock[] clocks = new Clock[] {
                    Clock.SIMPLE,
                    Clock.ACCURATE,
                    new Clock.Fast(executor)
            };

            for (Clock clock : clocks) {
                long drift = clock.getTime() - System.currentTimeMillis();
                assertTrue("unexpected drift: " + Math.abs(drift) + " (limit " + limit +")", Math.abs(drift) < limit); // Windows can have 15ms gaps
            }

            Thread.sleep(100);

            for (Clock clock : clocks) {
                long drift = clock.getTime() - System.currentTimeMillis();
                assertTrue("unexpected drift: " + Math.abs(drift) + " (limit " + limit +")", Math.abs(drift) < limit);
            }
        } finally {
            executor.shutdown();
        }
    }

    @Test
    public void testClockIncreasing() throws InterruptedException {
        ScheduledExecutorService executor =
                Executors.newSingleThreadScheduledExecutor();
        try {
            Clock[] clocks = new Clock[] {
                    Clock.SIMPLE,
                    Clock.ACCURATE,
                    new Clock.Fast(executor)
            };

            long[] time = new long[clocks.length];
            for (int i = 0; i < 10; i++) {
                for (int j = 0; j < clocks.length; j++) {
                    long now = clocks[j].getTimeIncreasing();
                    assertTrue(time[j] < now);
                    time[j] = now;
                }
            }
        } finally {
            executor.shutdown();
        }
    }

}<commit_msg>OAK-1564 - ClockTest on Windows fails: try to determine that actual (and current) granularity of System.currentTimeMillis() in order to have the correct test expectations<commit_after>/*
 * 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.jackrabbit.oak.stats;

import static junit.framework.Assert.assertTrue;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.junit.Test;

public class ClockTest {

    /**
     * Helper for checking how accurate the system clock is.
     */
    public static void main(String[] args) {
        System.out.println("average clock granularity: " + getAverageClockGranularity());
    }

    @Test
    public void testClockDrift() throws InterruptedException {
        ScheduledExecutorService executor =
                Executors.newSingleThreadScheduledExecutor();
        final long granularity = getAverageClockGranularity();
        final long limit = (2 * granularity) / 1000; // allow a drift twice as high
        final String diag = "(estimated limit was " + limit + "ms, measured granularity was " + ( granularity / 1000f) + "ms)";

        try {
            Clock[] clocks = new Clock[] {
                    Clock.SIMPLE,
                    Clock.ACCURATE,
                    new Clock.Fast(executor)
            };

            for (Clock clock : clocks) {
                long drift = clock.getTime() - System.currentTimeMillis();
                assertTrue("unexpected drift: " + Math.abs(drift) + "ms " + diag, Math.abs(drift) <= limit);
            }

            Thread.sleep(100);

            for (Clock clock : clocks) {
                long drift = clock.getTime() - System.currentTimeMillis();
                assertTrue("unexpected drift: " + Math.abs(drift) + "ms " + diag, Math.abs(drift) <= limit);
            }
        } finally {
            executor.shutdown();
        }
    }

    @Test
    public void testClockIncreasing() throws InterruptedException {
        ScheduledExecutorService executor =
                Executors.newSingleThreadScheduledExecutor();
        try {
            Clock[] clocks = new Clock[] {
                    Clock.SIMPLE,
                    Clock.ACCURATE,
                    new Clock.Fast(executor)
            };

            long[] time = new long[clocks.length];
            for (int i = 0; i < 10; i++) {
                for (int j = 0; j < clocks.length; j++) {
                    long now = clocks[j].getTimeIncreasing();
                    assertTrue(time[j] < now);
                    time[j] = now;
                }
            }
        } finally {
            executor.shutdown();
        }
    }

    /**
     * On some systems (for instance Windows), the granularity of {@link System.currentTimeMillis} depends
     * on system-wide settings that can change depending on what applications are running
     * (see, for instance <a href="http://www.lifehacker.com.au/2009/05/hidden-windows-7-tool-troubleshoots-sleep-mode-problems/">http://www.lifehacker.com.au/2009/05/hidden-windows-7-tool-troubleshoots-sleep-mode-problems/</a>).
     * This method tries to measure the granularity.
     * @return average granularity of {@link System.currentTimeMillis} in 1/1000 of milliseconds
     */
    private static long getAverageClockGranularity() {
        long sum = 0;
        int samples = 20; // number of samples to take
        long last = System.currentTimeMillis();

        for (int i = 0; i < samples; i++) {
            long now = System.currentTimeMillis();
            while (now == last) {
                // busy-wait until return value changes
                now = System.currentTimeMillis();
            }
            sum += (now - last); // add the actual difference
            last = now;
        }

        // return average in 1/1000ms
        return (sum * 1000) / samples;
    }
}
{'fraction_non_alphanumeric': 0.0994858304436207, 'fraction_numerical': 0.010642114073896926, 'mean_word_length': 2.038140210679259, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4265078', 'n_tokens_mistral': 2309, 'n_tokens_neox': 2140, 'n_words': 695}