001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.classic.control;
015
016import java.util.Random;
017
018import ch.qos.logback.classic.Level;
019import ch.qos.logback.classic.corpus.RandomUtil;
020
021public class ScenarioRandomUtil {
022    private final static long SEED = 74130;
023
024    private final static Random random = new Random(SEED);
025    private final static int AVERAGE_ID_LEN = 32;
026    private final static int AVERAGE_ID_DEV = 16;
027
028    private final static int AVERAGE_CHILDREN_COUNT = 30;
029    private final static int CHILDREN_COUNT_VAR = 10;
030
031    public static boolean oneInFreq(int freq) {
032        return (random.nextInt(freq) % freq) == 0;
033    }
034
035    public static Level randomLevel() {
036        int rl = random.nextInt(6);
037        switch (rl) {
038        case 0:
039            return null;
040        case 1:
041            return Level.TRACE;
042        case 2:
043            return Level.DEBUG;
044        case 3:
045            return Level.INFO;
046        case 4:
047            return Level.WARN;
048        case 5:
049            return Level.ERROR;
050        default:
051            throw new IllegalStateException("rl should have been a value between 0 to 5, but it is " + rl);
052        }
053    }
054
055    public static String randomLoggerName(int average, int stdDeviation) {
056        int depth = RandomUtil.gaussianAsPositiveInt(random, average, stdDeviation);
057        StringBuilder buf = new StringBuilder();
058        for (int i = 0; i < depth; i++) {
059            if (i != 0) {
060                buf.append('.');
061            }
062            buf.append(randomId());
063        }
064        return buf.toString();
065    }
066
067    public static String randomId() {
068
069        int len = RandomUtil.gaussianAsPositiveInt(random, AVERAGE_ID_LEN, AVERAGE_ID_DEV);
070        StringBuilder buf = new StringBuilder();
071        for (int i = 0; i < len; i++) {
072            int offset = random.nextInt(26);
073            char c = (char) ('a' + offset);
074            buf.append(c);
075        }
076        return buf.toString();
077    }
078
079    /**
080     * Returns 3 for root, 3 for children of root, 9 for offspring of generation 2
081     * and 3, and for generations 4 and later, return 0 with probability 0.5 and a
082     * gaussian (average=AVERAGE_CHILDREN_COUNT) with probability 0.5.
083     * 
084     * @param name
085     * @return
086     */
087    public static int randomChildrenCount(String name) {
088        int dots = dotCount(name);
089        if (dots <= 1) {
090            return 3;
091        } else if (dots == 2 || dots == 3) {
092            return 9;
093        } else {
094            if (shouldHaveChildrenWithProbabilitz(0.5)) {
095                return RandomUtil.gaussianAsPositiveInt(random, AVERAGE_CHILDREN_COUNT, CHILDREN_COUNT_VAR);
096            } else {
097                return 0;
098            }
099        }
100
101    }
102
103    /**
104     * Returns true with probability p.
105     * 
106     * @param p
107     * @return
108     */
109    static boolean shouldHaveChildrenWithProbabilitz(double p) {
110        if (p < 0 || p > 1.0) {
111            throw new IllegalArgumentException("p must be a value between 0 and 1.0, it was " + p + " instead.");
112        }
113        double r = random.nextDouble();
114        if (r < p) {
115            return true;
116        } else {
117            return false;
118        }
119    }
120
121    static int dotCount(String s) {
122        int count = 0;
123        int len = s.length();
124        for (int i = 0; i < len; i++) {
125            char c = s.charAt(i);
126            if (c == '.') {
127                count++;
128            }
129        }
130        return count;
131    }
132}