001package daikon.test;
002
003import static java.util.logging.Level.INFO;
004import static org.junit.Assert.assertEquals;
005
006import daikon.FileIO;
007import daikon.ModBitTracker;
008import daikon.ValueTuple;
009import java.util.BitSet;
010import java.util.Random;
011import org.junit.BeforeClass;
012import org.junit.Test;
013
014public class ModBitTrackerTest {
015
016  // Plan:
017  // Create many different variables.  Give them a skewed distribution of
018  // random modbits so that it takes them a while to separate.  In the end,
019  // give them modbits so that they are all separated.  See if the results
020  // are as they should be.
021
022  // I should probably add some tests that test arguments other than 1 for
023  // the "count" argument to ModBitTracker.add().
024
025  /** Random seed */
026  private Random r = new Random(20031014L);
027
028  /** prepare for tests */
029  @BeforeClass
030  public static void setUpClass() {
031    daikon.LogHelper.setupLogs(INFO);
032    FileIO.new_decl_format = true;
033  }
034
035  private ModBitTracker makeModBitTracker(BitSet[] bitsets) {
036    int numvars = bitsets.length;
037    int numsamples = bitsets[0].size();
038
039    ModBitTracker result = new ModBitTracker(numvars);
040
041    Object[] vals = new Object[numvars];
042    int[] mods = new int[numvars];
043    // We'll reuse this ValueTuple throughout, side-effecting its mods array.
044    ValueTuple vt = ValueTuple.makeUninterned(vals, mods);
045    for (int sampleno = 0; sampleno < numsamples; sampleno++) {
046      for (int var = 0; var < numvars; var++) {
047        mods[var] = booleanToModBit(bitsets[var].get(sampleno));
048      }
049      result.add(vt, 1);
050    }
051    return result;
052  }
053
054  private void checkModBitTracker(ModBitTracker mbt, BitSet[] bitsets) {
055    int numvars = bitsets.length;
056    int numsamples = bitsets[0].size();
057
058    assertEquals(numvars, mbt.num_vars());
059    assertEquals(numsamples, mbt.num_samples());
060
061    for (int i = 0; i < numvars; i++) {
062      assertEquals(mbt.get(i), bitsets[i]);
063    }
064  }
065
066  private int booleanToModBit(boolean b) {
067    return (b ? ValueTuple.MODIFIED : ValueTuple.MISSING_NONSENSICAL);
068  }
069
070  private boolean randomModBoolean(int varno, int sampleno) {
071    boolean unusual = (r.nextInt(100) == 0);
072    boolean result;
073    if (varno % 2 == 0) {
074      result = (varno % 2 == 0);
075    } else {
076      result = ((varno + sampleno) % 2 == 0);
077    }
078    if (unusual) {
079      result = !result;
080    }
081    return result;
082  }
083
084  // Make numvars different unique random BitSets, each of size
085  // numsamples+numvars.  Then add duplicate_factor more BitSets (e.g., if
086  // duplicate_factor is 1, then double the number of BitSets), where each
087  // of the additional ones is a duplicate of one of the unique ones.
088
089  BitSet[] makeBitSets(int numvars, int numsamples, double duplicate_factor) {
090    int totalvars = (int) (numvars * (1 + duplicate_factor));
091    BitSet[] result = new BitSet[totalvars];
092    for (int var = 0; var < numvars; var++) {
093      BitSet bs = new BitSet(numsamples + numvars);
094      for (int sample = 0; sample < numsamples; sample++) {
095        bs.set(sample, randomModBoolean(var, sample));
096      }
097      // add samples that make all the variables unique
098      bs.set(numsamples + numvars - 1, false);
099      bs.set(numsamples + var, true);
100      result[var] = bs;
101    }
102    // Add duplicate BitSets.
103    for (int var = numvars; var < totalvars; var++) {
104      result[var] = (BitSet) result[r.nextInt(numvars)].clone();
105    }
106    return result;
107  }
108
109  public void oneModBitTrackerTest(int vars, int samples, double duplicate_factor) {
110    BitSet[] bitsets = makeBitSets(vars, samples, duplicate_factor);
111    ModBitTracker mbt = makeModBitTracker(bitsets);
112    checkModBitTracker(mbt, bitsets);
113    assertEquals(vars, mbt.num_sets());
114  }
115
116  @Test
117  public void testModBitTracker() {
118    oneModBitTrackerTest(1, 2, 0.0);
119    oneModBitTrackerTest(2, 2, 0.0);
120    oneModBitTrackerTest(5, 10, 0.0);
121    oneModBitTrackerTest(100, 1000, 5.0);
122  }
123}