/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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.facebook.litho.testing.testrunner;

import com.facebook.litho.ComponentsSystrace;
import org.junit.runners.model.InitializationError;
import org.robolectric.DefaultTestLifecycle;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.TestLifecycle;
import org.robolectric.annotation.Config;

public class LithoTestRunner extends RobolectricTestRunner {
  /**
   * Creates a runner to run {@code testClass}. Looks in your working directory for your
   * AndroidManifest.xml file and res directory by default. Use the {@link Config} annotation to
   * configure.
   *
   * @param testClass the test class to be run
   * @throws InitializationError if junit says so
   */
  public LithoTestRunner(final Class<?> testClass) throws InitializationError {
    super(testClass);
  }

  @Override
  protected Config buildGlobalConfig() {
    // If we're running with gradle, the test runner will start running from within
    // the given sub-project.
    if (System.getProperty("org.gradle.test.worker") != null) {
      return new Config.Builder().setManifest("../litho-it/src/main/AndroidManifest.xml").build();
    }

    // BUCK will set up the manifest correctly, so nothing to do here.
    return super.buildGlobalConfig();
  }

  @Override
  protected Class<? extends TestLifecycle> getTestLifecycleClass() {
    return LithoTestLifecycle.class;
  }

  public static class LithoTestLifecycle extends DefaultTestLifecycle {
    public LithoTestLifecycle() {
      ComponentsSystrace.provide(NoOpComponentsSystrace.sInstance);
    }
  }
}

@@ -705,16 +705,222 @@
 strace;%0A
+import com.facebook.litho.config.ComponentsConfiguration;%0Aimport java.lang.reflect.Field;%0Aimport java.lang.reflect.Method;%0Aimport java.lang.reflect.Modifier;%0Aimport java.util.HashMap;%0Aimport java.util.Map;%0A
 import o
@@ -2265,16 +2265,86 @@
 cycle %7B%0A
+%0A    private final Map%3CField, Object%3E mSavedComponentsConfiguration;%0A%0A
     publ
@@ -2437,16 +2437,1285 @@
 tance);%0A
+      mSavedComponentsConfiguration = recordComponentsConfiguration();%0A    %7D%0A%0A    @Override%0A    public void afterTest(Method method) %7B%0A      super.afterTest(method);%0A      restoreComponentsConfiguration(mSavedComponentsConfiguration);%0A    %7D%0A%0A    private static Map%3CField, Object%3E recordComponentsConfiguration() %7B%0A      final HashMap%3CField, Object%3E record = new HashMap%3C%3E();%0A      for (Field f : ComponentsConfiguration.class.getDeclaredFields()) %7B%0A        final int modifiers = f.getModifiers();%0A        if (Modifier.isStatic(modifiers)%0A            && Modifier.isPublic(modifiers)%0A            && !Modifier.isFinal(modifiers)) %7B%0A          try %7B%0A            record.put(f, f.get(null));%0A          %7D catch (IllegalAccessException e) %7B%0A            throw new RuntimeException(%22Couldn't record ComponentsConfiguration state%22, e);%0A          %7D%0A        %7D%0A      %7D%0A      return record;%0A    %7D%0A%0A    private static void restoreComponentsConfiguration(Map%3CField, Object%3E fieldsToValues) %7B%0A      for (Map.Entry%3CField, Object%3E entry : fieldsToValues.entrySet()) %7B%0A        try %7B%0A          entry.getKey().set(null, entry.getValue());%0A        %7D catch (IllegalAccessException e) %7B%0A          throw new RuntimeException(%22Couldn't restore ComponentsConfiguration state%22, e);%0A        %7D%0A      %7D%0A
     %7D%0A  

Reset ComponentsConfiguration after each Litho test