Package com.google.test.metric

Source Code of com.google.test.metric.MetricComputerTest$Singleton

/*
* Copyright 2007 Google Inc.
*
* Licensed 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 com.google.test.metric;

import static com.google.classpath.ClasspathRootFactory.makeClasspathRootGroup;
import static com.google.test.metric.SignatureUtil.L;

import com.google.test.metric.report.DrillDownReport;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.List;

public class MetricComputerTest extends ClassRepositoryTestCase {

  private MetricComputer computer;
  private final RegExpWhiteList whitelist = new RegExpWhiteList();

  @Override
  protected void setUp() throws Exception {
    super.setUp();
    computer = new MetricComputer(repo, null, whitelist, new CostModel());
  }

  public static class Medium {
    public Medium() {
      statiCost1();
      cost2();
    }

    /**
     * I cost 1
     */
    public static int statiCost1() {
      int i = 0;
      return i > 0 ? 1 : 2;
    }

    /**
     * I cost 2, but I am instance method so I can be overridden. so my cost may
     * be avoided in most cases.
     */
    public int cost2() {
      int i = 0;
      return i > 0 ? i > 1 ? 1 : 2 : 2;
    }

    /**
     * I am instance method hence you will have to add the cost of constructor
     * to me. (by myself I cost 4)
     */
    public Object testMethod4() {
      int i = 0;
      i = i > 0 ? 1 : 2;
      i = i > 0 ? 1 : 2;
      i = i > 0 ? 1 : 2;
      i = i > 0 ? 1 : 2;
      return new Object();
    }
  }

  public void testMediumCost1() throws Exception {
    MethodInfo method = repo.getClass(Medium.class).getMethod("statiCost1()I");
    assertFalse(method.canOverride());
    MethodCost cost = computer.compute(Medium.class, "statiCost1()I");
    assertEquals(1l, cost.getTotalComplexityCost());
  }

  /**
   * Since cost2 is called twice, once by our test and once by constructor we
   * don't want to add it twice. But the constructor adds 1 so total cost is 3.
   */
  public void testMediumCost2() throws Exception {
    MethodInfo method = repo.getClass(Medium.class).getMethod("cost2()I");
    assertTrue(method.canOverride());
    MethodCost cost = computer.compute(Medium.class, "cost2()I");
    assertEquals(3l, cost.getTotalComplexityCost());
  }

  /**
   * Cost of the constructor needs to add the cost of the static method it calls
   * as it can not be overridden but not the cost of the instance method.
   */
  public void testMediumInit() throws Exception {
    MethodInfo method = repo.getClass(Medium.class).getMethod("<init>()V");
    assertFalse(method.canOverride());
    MethodCost cost = computer.compute(Medium.class, "<init>()V");
    assertEquals(1l, cost.getTotalComplexityCost());
  }

  /**
   * Method4 is cost of 4 by itself, but one has the add the cost of constructor
   * since it is an instance method. The constructor is 0 but calls to methods:
   * cost1 method is static and can not be intercepted hence it has to be added.
   * cost2 method is instance and can be overridden hence we don't add that
   * cost.
   */
  public void testMediumMethod4() throws Exception {
    MethodCost cost = computer.compute(Medium.class,
        "testMethod4()Ljava/lang/Object;");
    assertEquals(5l, cost.getTotalComplexityCost());
  }

  public static class Node {
    public String cost1() {
      int a = 0;
      return a == 2 ? "" : null;
    }
  }

  public static class Tree {
    private Node subTitle; // non-injectable
    public Node title = new Node(); // injectable (only after constructor)

    public Tree() {
    }

    public String titleLength() {
      return title.cost1();
    }

    public String subTitleLength() {
      return subTitle.cost1();
    }

    public String veryExpensive() {
      return "".toLowerCase();
    }
  }

  public void testTree() throws Exception {
    MethodCost cost = computer.compute(Tree.class, "<init>()V");
    assertEquals(0l, cost.getTotalComplexityCost());
  }

  public void testTreeTitleLength() throws Exception {
    MethodCost cost = computer.compute(Tree.class,
        "titleLength()Ljava/lang/String;");
    assertEquals(0l, cost.getTotalComplexityCost());
  }

  public void testTreeSubTitleLength() throws Exception {
    MethodCost cost = computer.compute(Tree.class,
        "subTitleLength()Ljava/lang/String;");
    assertEquals(1l, cost.getTotalComplexityCost());
  }

  public void testVeryExpensive() throws Exception {
    MethodCost cost = computer.compute(Tree.class,
        "veryExpensive()Ljava/lang/String;");
    assertTrue("100<"+cost.getTotalComplexityCost(), 100l < cost.getTotalComplexityCost());
  }

  static class ChoseConstructor {
    ChoseConstructor() {
    }

    ChoseConstructor(Object a) {
    }

    ChoseConstructor(Object a, int c, int d) {
    }

    ChoseConstructor(Object a, Object b) {
    }
  }

  public void testChooseConstructorWithMostParameters() throws Exception {
    ClassInfo classInfo = repo.getClass(ChoseConstructor.class);
    MethodInfo constructor = computer.getPrefferedConstructor(classInfo);
    assertEquals("<init>(Ljava/lang/Object;Ljava/lang/Object;)V", constructor
        .getNameDesc());
  }

  static class Singleton {
    private Singleton() {
      CostUtil.staticCost1();
    }

    public void doWork() {
      CostUtil.staticCost2();
    }
  }

  public void testIgnoreConstructorsIfAllConstructorsArePrivate()
      throws Exception {
    assertEquals(2L, computer.compute(Singleton.class, "doWork()V")
        .getTotalComplexityCost());
  }

  static class StaticInit {
    static {
      CostUtil.staticCost1();
    }

    public void doWork() {
      CostUtil.staticCost2();
    }
  }

  public void testAddStaticInitializationCost() throws Exception {
    assertEquals(3L, computer.compute(StaticInit.class, "doWork()V")
        .getTotalComplexityCost());
  }

  static class Setters {
    private Object o;

    public void setO(Object o) {
      this.o = o;
    }

    public void doWork() {
      o.toString();
    }
  }

  public void testSetterInjection() throws Exception {
    assertEquals(0L, computer.compute(Setters.class, "doWork()V")
        .getTotalComplexityCost());
  }

  static class WholeClassCost {
    void methodA() {
      CostUtil.staticCost1();
    }

    void methodB() {
      CostUtil.staticCost1();
    }
  }

  public void testComputeClassCost() throws Exception {
    ClassCost cost = computer.compute(WholeClassCost.class);
    assertEquals(1L, cost.getMethodCost("methodA()V").getTotalComplexityCost());
    assertEquals(1L, cost.getMethodCost("methodB()V").getTotalComplexityCost());
  }

  static class Array {
    String[] strings;

    public void method() {
      strings.clone();
    }
  }

  public void testArray() throws Exception {
    repo.getClass(String[].class);
    computer.compute(repo.getClass(Array.class).getMethod("method()V"));
  }

  static class InjectableClass {
    public void cost4() {
      CostUtil.staticCost4();
    }

    public static void callCost0(InjectableClass ref) {
      indirection(ref);
    }

    private static void indirection(InjectableClass ref) {
      ref.cost4();
    }
    public static void callCost4() {
      InjectableClass x = new InjectableClass();
      indirection(x);
    }
  }

  public void testInjectabilityIsTransitive() throws Exception {
    ClassCost cost = computer.compute(InjectableClass.class);
    MethodCost callCost0 = cost.getMethodCost("callCost0("
        + L(InjectableClass.class) + ")V");
    MethodCost callCost4 = cost.getMethodCost("callCost4()V");
    assertEquals(0L, callCost0.getTotalComplexityCost());
    assertEquals(4L, callCost4.getTotalComplexityCost());
  }

  static class GlobalState {
    int i;
    static final String X = "X";

    public int inc() {
      return i++;
    }

    public void noop() {
    }

    @Override
    public String toString() {
      return X;
    }
  }

  static final GlobalState ref = new GlobalState();
  static int count;
  static class GlobalStateUser {

    // StateLoad: 0
    public void noLoad() {
    }

    // StateLoad: 1
    public void accessCount() {
      count++;
    }

    // StateLoad: 0
    public void accessFinalState() {
      ref.noop();
    }

    // StateLoad: 0
    public void accessFinalState2() {
      ref.toString();
    }

    // StateLoad: 1
    public void accessMutableState() {
      ref.inc();
    }
  }

  public void testGlobalLoadWhichAccessesFinalShouldBeZero() {
    ClassCost cost = computer.compute(GlobalState.class);
    MethodCost method = cost.getMethodCost("toString()Ljava/lang/String;");
    assertEquals(0L, method.getTotalGlobalCost());
  }

  public void testGlobalLoadMethodDispatchNoStateAccessShouldBeZero() {
    ClassCost cost = computer.compute(GlobalStateUser.class);
    assertEquals(0L, cost.getMethodCost("noLoad()V").getTotalGlobalCost());
    assertEquals(0L, cost.getMethodCost("accessFinalState()V")
        .getTotalGlobalCost());
    assertEquals(0L, cost.getMethodCost("accessFinalState2()V")
        .getTotalGlobalCost());
  }

  public void testGlobalLoadAccessStateShouldBeOne() {
    MethodCost cost = computer.compute(GlobalStateUser.class, "accessCount()V");
    assertEquals(1L, cost.getTotalGlobalCost());
  }

  public void testGlobalLoadAccessStateThroughFinalShouldBeOne() {
    MethodCost cost =
        computer.compute(GlobalStateUser.class, "accessMutableState()V");
    new DrillDownReport(new PrintStream(new ByteArrayOutputStream()),
        null, Integer.MAX_VALUE, 0).print("", cost, 10);
    assertEquals("Expecting one for read and one for write", 2L,
        cost.getTotalGlobalCost());
  }

  public void testJavaLangObjectParsesCorrectly() throws Exception {
    repo.getClass(Object.class);
  }

  public static class CostPerLine {
    static void main(){
      CostUtil.staticCost0(); // line0
      CostUtil.staticCost1(); // line1
      CostUtil.staticCost2(); // line2
    }
  }

  public void testCostPerLine() throws Exception {
    MethodCost cost = computer.compute(CostPerLine.class, "main()V");
    assertEquals(3, cost.getTotalComplexityCost());
    List<LineNumberCost> lineNumberCosts = cost.getOperationCosts();
    assertEquals(3, lineNumberCosts.size());

    LineNumberCost line0 = lineNumberCosts.get(0);
    LineNumberCost line1 = lineNumberCosts.get(1);
    LineNumberCost line2 = lineNumberCosts.get(2);

    int methodStartingLine = cost.getMethodLineNumber();

    assertEquals(0, line0.getMethodCost().getTotalComplexityCost());
    assertEquals(methodStartingLine + 0, line0.getLineNumber());

    assertEquals(1, line1.getMethodCost().getTotalComplexityCost());
    assertEquals(methodStartingLine + 1, line1.getLineNumber());

    assertEquals(2, line2.getMethodCost().getTotalComplexityCost());
    assertEquals(methodStartingLine + 2, line2.getLineNumber());
  }

  public static class WhiteListTest {
    public void testMethod() {
      new String(new byte[0]);
    }
  }

  public void testWhiteList() throws Exception {
    RegExpWhiteList whiteList = new RegExpWhiteList("java.lang");
    computer = new MetricComputer(repo, null, whiteList, new CostModel());
    MethodCost cost = computer.compute(WhiteListTest.class, "testMethod()V");
    assertEquals(0L, cost.getTotalGlobalCost());
  }

  public void testThatOnWindowsWeCanParseTheFonts() throws Exception {
    repo = new ClassRepository(makeClasspathRootGroup("classes-for-test/jre1.6_TrueTypeBug"));
    WhiteList whitelist = new RegExpWhiteList();
    computer = new MetricComputer(repo, null, whitelist, new CostModel());
    ClassInfo clazz = repo.getClass("sun.font.TrueTypeFont");
    MethodInfo method = clazz.getMethod("getTableBuffer(I)Ljava/nio/ByteBuffer;");
    computer.compute(method);
    // assert no exception thrown.
  }

  static class DoubleCountClassConst {
    static int x;
    static {
      x = 1;
    }
  }
  public void testDoubleCountClassConst() throws Exception {
    ClassCost cost = computer.compute(DoubleCountClassConst.class);
    assertEquals(1, cost.getMethodCost("<clinit>()V").getTotalGlobalCost());
  }

  static enum TestEnum1{ ONE }
  public void testEnumerationIsZero() throws Exception {
    whitelist.addPackage("java.");
    ClassCost cost = computer.compute(TestEnum1.class);
    assertEquals(0, cost.getMethodCost("<clinit>()V").getTotalGlobalCost());
  }

  private final String testValue = null;
  class InnerClassTest {
    public void test() {
      testValue.indexOf(0);
    }
  }
  public void XtestInnerClassInjectability() throws Exception {
    MethodCost cost = computer.compute(InnerClassTest.class, "test()V");
    assertEquals(0, cost.getTotalComplexityCost());
  }

}
TOP

Related Classes of com.google.test.metric.MetricComputerTest$Singleton

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.