<commit_before>/*
 * JMockit Expectations & Verifications
 * Copyright (c) 2006-2010 <NAME>
 * All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package mockit;

import java.io.*;
import java.util.*;

import org.junit.*;

import static org.junit.Assert.*;

public final class DynamicPartialMockingTest
{
   static class Collaborator
   {
      protected final int value;

      Collaborator() { value = -1; }
      Collaborator(int value) { this.value = value; }

      int getValue() { return value; }

      @SuppressWarnings({"UnusedDeclaration"})
      final boolean simpleOperation(int a, String b, Date c) { return true; }

      @SuppressWarnings({"UnusedDeclaration"})
      static void doSomething(boolean b, String s) { throw new IllegalStateException(); }

      boolean methodWhichCallsAnotherInTheSameClass()
      {
         return simpleOperation(1, "internal", null);
      }
   }

   static final class SubCollaborator extends Collaborator
   {
      SubCollaborator() { this(1); }
      SubCollaborator(int value) { super(value); }

      String format() { return String.valueOf(value); }
   }

   interface Dependency
   {
      boolean doSomething();
      List<?> doSomethingElse(int n);
   }

   @Test
   public void dynamicallyMockAClass()
   {
      new Expectations(Collaborator.class)
      {
         {
            new Collaborator().getValue(); result = 123;
         }
      };

      // Mocked:
      Collaborator collaborator = new Collaborator();
      assertEquals(123, collaborator.getValue());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(1, "b", null));
      assertEquals(45, new Collaborator(45).value);
   }

   @Test
   public void dynamicallyMockAMockedClass(@Mocked final Collaborator mock)
   {
      assertEquals(0, mock.value);

      new Expectations(mock)
      {
         {
            mock.getValue(); result = 123;
         }
      };

      // Mocked:
      assertEquals(123, mock.getValue());

      // Not mocked:
      Collaborator collaborator = new Collaborator();
      assertEquals(-1, collaborator.value);
      assertTrue(collaborator.simpleOperation(1, "b", null));
      assertEquals(45, new Collaborator(45).value);
   }

   @Test
   public void dynamicallyMockAnInstance()
   {
      final Collaborator collaborator = new Collaborator();

      new Expectations(collaborator)
      {
         {
            collaborator.getValue(); result = 123;
         }
      };

      // Mocked:
      assertEquals(123, collaborator.getValue());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(1, "b", null));
      assertEquals(45, new Collaborator(45).value);
      assertEquals(-1, new Collaborator().value);
   }

   @Test(expected = AssertionError.class)
   public void expectTwoInvocationsOnStrictDynamicMockButReplayOnce()
   {
      final Collaborator collaborator = new Collaborator();

      new Expectations(collaborator)
      {
         {
            collaborator.getValue(); times = 2;
         }
      };

      assertEquals(0, collaborator.getValue());
   }

   @Test
   public void expectOneInvocationOnStrictDynamicMockButReplayTwice()
   {
      final Collaborator collaborator = new Collaborator(1);

      new Expectations(collaborator)
      {
         {
            collaborator.methodWhichCallsAnotherInTheSameClass(); result = false;
         }
      };

      // Mocked:
      assertFalse(collaborator.methodWhichCallsAnotherInTheSameClass());

      // No longer mocked, since it's strict:
      assertTrue(collaborator.methodWhichCallsAnotherInTheSameClass());
   }

   @Test
   public void expectTwoInvocationsOnStrictDynamicMockButReplayMoreTimes()
   {
      final Collaborator collaborator = new Collaborator(1);

      new Expectations(collaborator)
      {
         {
            collaborator.getValue(); times = 2;
         }
      };

      // Mocked:
      assertEquals(0, collaborator.getValue());
      assertEquals(0, collaborator.getValue());

      // No longer mocked, since it's strict and all expected invocations were already replayed:
      assertEquals(1, collaborator.getValue());
   }

   @Test(expected = AssertionError.class)
   public void expectTwoInvocationsOnNonStrictDynamicMockButReplayOnce()
   {
      final Collaborator collaborator = new Collaborator();

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.getValue(); times = 2;
         }
      };

      assertEquals(0, collaborator.getValue());
   }

   @Test(expected = AssertionError.class)
   public void expectOneInvocationOnNonStrictDynamicMockButReplayTwice()
   {
      final Collaborator collaborator = new Collaborator(1);

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.getValue(); times = 1;
         }
      };

      // Mocked:
      assertEquals(0, collaborator.getValue());

      // Still mocked because it's non-strict:
      assertEquals(0, collaborator.getValue());
   }

   @Test
   public void dynamicallyMockAnInstanceWithNonStrictExpectations()
   {
      final Collaborator collaborator = new Collaborator(2);

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.simpleOperation(1, "", null); result = false;
            Collaborator.doSomething(anyBoolean, "test");
         }
      };

      // Mocked:
      assertFalse(collaborator.simpleOperation(1, "", null));
      Collaborator.doSomething(true, "test");

      // Not mocked:
      assertEquals(2, collaborator.getValue());
      assertEquals(45, new Collaborator(45).value);
      assertEquals(-1, new Collaborator().value);

      try {
         Collaborator.doSomething(false, null);
         fail();
      }
      catch (IllegalStateException ignore) {}

      new Verifications()
      {
         {
            Collaborator.doSomething(anyBoolean, "test");
            collaborator.getValue(); times = 1;
            new Collaborator(45);
         }
      };
   }

   @Test
   public void mockMethodInSameClass()
   {
      final Collaborator collaborator = new Collaborator();

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.simpleOperation(1, anyString, null); result = false;
         }
      };

      assertFalse(collaborator.methodWhichCallsAnotherInTheSameClass());
      assertTrue(collaborator.simpleOperation(2, "", null));
      assertFalse(collaborator.simpleOperation(1, "", null));
   }

   @Test(expected = IllegalStateException.class)
   public void dynamicallyMockASubCollaboratorInstance()
   {
      final SubCollaborator collaborator = new SubCollaborator();

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.getValue(); result = 5;
            new SubCollaborator().format(); result = "test";
         }
      };

      // Mocked:
      assertEquals(5, collaborator.getValue());
      assertEquals("test", collaborator.format());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(0, null, null));
      Collaborator.doSomething(true, null); // will throw the IllegalStateException
   }

   @Test
   public void dynamicallyMockOnlyTheSubclass()
   {
      final SubCollaborator collaborator = new SubCollaborator();

      new NonStrictExpectations(SubCollaborator.class)
      {
         {
            collaborator.getValue();
            collaborator.format(); result = "test";
         }
      };

      // Mocked:
      assertEquals("test", collaborator.format());

      // Not mocked:
      assertEquals(1, collaborator.getValue());
      assertTrue(collaborator.simpleOperation(0, null, null));

      // Mocked sub-constructor/not mocked base constructor:
      assertEquals(-1, new SubCollaborator().value);

      new VerificationsInOrder()
      {
         {
            collaborator.format();
            new SubCollaborator();
         }
      };
   }

   @Test
   public void dynamicallyMockAnAnonymousClassInstanceThroughTheImplementedInterface()
   {
      final Collaborator collaborator = new Collaborator();

      final Dependency dependency = new Dependency()
      {
         public boolean doSomething() { return false; }
         public List<?> doSomethingElse(int n) { return null; }
      };
      
      new NonStrictExpectations(collaborator, dependency)
      {
         {
            collaborator.getValue(); result = 5;
            dependency.doSomething(); result = true;
         }
      };

      // Mocked:
      assertEquals(5, collaborator.getValue());
      assertTrue(dependency.doSomething());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(0, null, null));
      assertNull(dependency.doSomethingElse(3));

      new FullVerifications()
      {
         {
            dependency.doSomething();
            collaborator.getValue();
            dependency.doSomethingElse(anyInt);
            collaborator.simpleOperation(0, null, null);
         }
      };
   }

   @Test
   public void dynamicallyMockJREClass()
   {
      final List<String> list = new LinkedList<String>();

      new NonStrictExpectations(list)
      {
         {
            list.get(1); result = "an item";
            list.size(); result = 2;
         }
      };

      // Use mocked methods:
      assertEquals(2, list.size());
      assertEquals("an item", list.get(1));

      // Use unmocked methods:
      assertTrue(list.add("another"));
      assertEquals("another", list.remove(0));
   }

   @Test
   public void attemptToUseDynamicMockingForInvalidTypes()
   {
      assertInvalidTypeForDynamicMocking(Dependency.class);
      assertInvalidTypeForDynamicMocking(Test.class);
      assertInvalidTypeForDynamicMocking(int[].class);
      assertInvalidTypeForDynamicMocking(new String[1]);
      assertInvalidTypeForDynamicMocking(char.class);
      assertInvalidTypeForDynamicMocking(123);
      assertInvalidTypeForDynamicMocking(Boolean.class);
      assertInvalidTypeForDynamicMocking(true);
      assertInvalidTypeForDynamicMocking(2.5);
      assertInvalidTypeForDynamicMocking(Mockit.newEmptyProxy(Dependency.class));
   }

   private void assertInvalidTypeForDynamicMocking(Object classOrObject)
   {
      try {
         new Expectations(classOrObject) {};
         fail();
      }
      catch (IllegalArgumentException ignore) {}
   }

   @Test
   public void dynamicPartialMockingWithExactArgumentMatching()
   {
      final Collaborator collaborator = new Collaborator();

      new NonStrictExpectations(collaborator)
      {{
         collaborator.simpleOperation(1, "s", null); result = false;
      }};

      assertFalse(collaborator.simpleOperation(1, "s", null));
      assertTrue(collaborator.simpleOperation(2, "s", null));
      assertTrue(collaborator.simpleOperation(1, "S", null));
      assertTrue(collaborator.simpleOperation(1, "s", new Date()));
      assertTrue(collaborator.simpleOperation(1, null, new Date()));
      assertFalse(collaborator.simpleOperation(1, "s", null));

      new FullVerifications()
      {
         {
            collaborator.simpleOperation(anyInt, null, null);
         }
      };
   }

   @Test
   public void dynamicPartialMockingWithFlexibleArgumentMatching(final Collaborator mock)
   {
      new NonStrictExpectations(mock)
      {{
         mock.simpleOperation(anyInt, withPrefix("s"), null); result = false;
      }};

      Collaborator collaborator = new Collaborator();
      assertFalse(collaborator.simpleOperation(1, "sSs", null));
      assertTrue(collaborator.simpleOperation(2, " s", null));
      assertTrue(collaborator.simpleOperation(1, "S", null));
      assertFalse(collaborator.simpleOperation(-1, "s", new Date()));
      assertTrue(collaborator.simpleOperation(1, null, null));
      assertFalse(collaborator.simpleOperation(0, "string", null));
   }

   @Test
   public void dynamicPartialMockingWithOnInstanceMatching()
   {
      final Collaborator mock = new Collaborator();

      new NonStrictExpectations(mock)
      {{
         onInstance(mock).getValue(); result = 3;
      }};

      assertEquals(3, mock.getValue());
      assertEquals(4, new Collaborator(4).getValue());

      new FullVerificationsInOrder()
      {
         {
            onInstance(mock).getValue();
            mock.getValue();
         }
      };
   }

   @Test
   public void methodWithNoRecordedExpectationCalledTwiceDuringReplay()
   {
      final Collaborator collaborator = new Collaborator(123);

      new NonStrictExpectations(collaborator) {};

      assertEquals(123, collaborator.getValue());
      assertEquals(123, collaborator.getValue());

      new FullVerifications()
      {
         {
            collaborator.getValue(); times = 2;
         }
      };
   }

   static final class TaskWithConsoleInput
   {
      boolean finished;

      void doIt()
      {
         int input = '\0';

         while (input != 'A') {
            try {
               input = System.in.read();
            }
            catch (IOException e) {
               throw new RuntimeException(e);
            }

            if (input == 'Z') {
               finished = true;
               break;
            }
         }
      }
   }

   private boolean runTaskWithTimeout(long timeoutInMillis) throws InterruptedException
   {
      final TaskWithConsoleInput task = new TaskWithConsoleInput();

      while (!task.finished) {
         Thread worker = new Thread(new Runnable()
         {
            public void run() { task.doIt(); }
         });
         worker.start();
         worker.join(timeoutInMillis);

         if (worker.isAlive()) {
            return false;
         }
      }

      return true;
   }

   @Test
   public void taskWithConsoleInputTerminatingNormally() throws Exception
   {
      new Expectations(System.in)
      {
         {
            System.in.read(); returns((int) 'A', (int) 'x', (int) 'Z');<commit_msg>Fixed minor issue in a test.<commit_after>/*
 * JMockit Expectations & Verifications
 * Copyright (c) 2006-2010 <NAME>
 * All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package mockit;

import java.io.*;
import java.util.*;

import org.junit.*;

import static org.junit.Assert.*;

public final class DynamicPartialMockingTest
{
   static class Collaborator
   {
      protected final int value;

      Collaborator() { value = -1; }
      Collaborator(int value) { this.value = value; }

      int getValue() { return value; }

      @SuppressWarnings({"UnusedDeclaration"})
      final boolean simpleOperation(int a, String b, Date c) { return true; }

      @SuppressWarnings({"UnusedDeclaration"})
      static void doSomething(boolean b, String s) { throw new IllegalStateException(); }

      boolean methodWhichCallsAnotherInTheSameClass()
      {
         return simpleOperation(1, "internal", null);
      }
   }

   static final class SubCollaborator extends Collaborator
   {
      SubCollaborator() { this(1); }
      SubCollaborator(int value) { super(value); }

      String format() { return String.valueOf(value); }
   }

   interface Dependency
   {
      boolean doSomething();
      List<?> doSomethingElse(int n);
   }

   @Test
   public void dynamicallyMockAClass()
   {
      new Expectations(Collaborator.class)
      {
         {
            new Collaborator().getValue(); result = 123;
         }
      };

      // Mocked:
      Collaborator collaborator = new Collaborator();
      assertEquals(123, collaborator.getValue());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(1, "b", null));
      assertEquals(45, new Collaborator(45).value);
   }

   @Test
   public void dynamicallyMockAMockedClass(@Mocked final Collaborator mock)
   {
      assertEquals(0, mock.value);

      new Expectations(mock)
      {
         {
            mock.getValue(); result = 123;
         }
      };

      // Mocked:
      assertEquals(123, mock.getValue());

      // Not mocked:
      Collaborator collaborator = new Collaborator();
      assertEquals(-1, collaborator.value);
      assertTrue(collaborator.simpleOperation(1, "b", null));
      assertEquals(45, new Collaborator(45).value);
   }

   @Test
   public void dynamicallyMockAnInstance()
   {
      final Collaborator collaborator = new Collaborator();

      new Expectations(collaborator)
      {
         {
            collaborator.getValue(); result = 123;
         }
      };

      // Mocked:
      assertEquals(123, collaborator.getValue());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(1, "b", null));
      assertEquals(45, new Collaborator(45).value);
      assertEquals(-1, new Collaborator().value);
   }

   @Test(expected = AssertionError.class)
   public void expectTwoInvocationsOnStrictDynamicMockButReplayOnce()
   {
      final Collaborator collaborator = new Collaborator();

      new Expectations(collaborator)
      {
         {
            collaborator.getValue(); times = 2;
         }
      };

      assertEquals(0, collaborator.getValue());
   }

   @Test
   public void expectOneInvocationOnStrictDynamicMockButReplayTwice()
   {
      final Collaborator collaborator = new Collaborator(1);

      new Expectations(collaborator)
      {
         {
            collaborator.methodWhichCallsAnotherInTheSameClass(); result = false;
         }
      };

      // Mocked:
      assertFalse(collaborator.methodWhichCallsAnotherInTheSameClass());

      // No longer mocked, since it's strict:
      assertTrue(collaborator.methodWhichCallsAnotherInTheSameClass());
   }

   @Test
   public void expectTwoInvocationsOnStrictDynamicMockButReplayMoreTimes()
   {
      final Collaborator collaborator = new Collaborator(1);

      new Expectations(collaborator)
      {
         {
            collaborator.getValue(); times = 2;
         }
      };

      // Mocked:
      assertEquals(0, collaborator.getValue());
      assertEquals(0, collaborator.getValue());

      // No longer mocked, since it's strict and all expected invocations were already replayed:
      assertEquals(1, collaborator.getValue());
   }

   @Test(expected = AssertionError.class)
   public void expectTwoInvocationsOnNonStrictDynamicMockButReplayOnce()
   {
      final Collaborator collaborator = new Collaborator();

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.getValue(); times = 2;
         }
      };

      assertEquals(0, collaborator.getValue());
   }

   @Test(expected = AssertionError.class)
   public void expectOneInvocationOnNonStrictDynamicMockButReplayTwice()
   {
      final Collaborator collaborator = new Collaborator(1);

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.getValue(); times = 1;
         }
      };

      // Mocked:
      assertEquals(0, collaborator.getValue());

      // Still mocked because it's non-strict:
      assertEquals(0, collaborator.getValue());
   }

   @Test
   public void dynamicallyMockAnInstanceWithNonStrictExpectations()
   {
      final Collaborator collaborator = new Collaborator(2);

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.simpleOperation(1, "", null); result = false;
            Collaborator.doSomething(anyBoolean, "test");
         }
      };

      // Mocked:
      assertFalse(collaborator.simpleOperation(1, "", null));
      Collaborator.doSomething(true, "test");

      // Not mocked:
      assertEquals(2, collaborator.getValue());
      assertEquals(45, new Collaborator(45).value);
      assertEquals(-1, new Collaborator().value);

      try {
         Collaborator.doSomething(false, null);
         fail();
      }
      catch (IllegalStateException ignore) {}

      new Verifications()
      {
         {
            Collaborator.doSomething(anyBoolean, "test");
            collaborator.getValue(); times = 1;
            new Collaborator(45);
         }
      };
   }

   @Test
   public void mockMethodInSameClass()
   {
      final Collaborator collaborator = new Collaborator();

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.simpleOperation(1, anyString, null); result = false;
         }
      };

      assertFalse(collaborator.methodWhichCallsAnotherInTheSameClass());
      assertTrue(collaborator.simpleOperation(2, "", null));
      assertFalse(collaborator.simpleOperation(1, "", null));
   }

   @Test(expected = IllegalStateException.class)
   public void dynamicallyMockASubCollaboratorInstance()
   {
      final SubCollaborator collaborator = new SubCollaborator();

      new NonStrictExpectations(collaborator)
      {
         {
            collaborator.getValue(); result = 5;
            new SubCollaborator().format(); result = "test";
         }
      };

      // Mocked:
      assertEquals(5, collaborator.getValue());
      assertEquals("test", collaborator.format());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(0, null, null));
      Collaborator.doSomething(true, null); // will throw the IllegalStateException
   }

   @Test
   public void dynamicallyMockOnlyTheSubclass()
   {
      final SubCollaborator collaborator = new SubCollaborator();

      new NonStrictExpectations(SubCollaborator.class)
      {
         {
            collaborator.getValue();
            collaborator.format(); result = "test";
         }
      };

      // Mocked:
      assertEquals("test", collaborator.format());

      // Not mocked:
      assertEquals(1, collaborator.getValue());
      assertTrue(collaborator.simpleOperation(0, null, null));

      // Mocked sub-constructor/not mocked base constructor:
      assertEquals(-1, new SubCollaborator().value);

      new VerificationsInOrder()
      {
         {
            collaborator.format();
            new SubCollaborator();
         }
      };
   }

   @Test
   public void dynamicallyMockAnAnonymousClassInstanceThroughTheImplementedInterface()
   {
      final Collaborator collaborator = new Collaborator();

      final Dependency dependency = new Dependency()
      {
         public boolean doSomething() { return false; }
         public List<?> doSomethingElse(int n) { return null; }
      };
      
      new NonStrictExpectations(collaborator, dependency)
      {
         {
            collaborator.getValue(); result = 5;
            dependency.doSomething(); result = true;
         }
      };

      // Mocked:
      assertEquals(5, collaborator.getValue());
      assertTrue(dependency.doSomething());

      // Not mocked:
      assertTrue(collaborator.simpleOperation(0, null, null));
      assertNull(dependency.doSomethingElse(3));

      new FullVerifications()
      {
         {
            dependency.doSomething();
            collaborator.getValue();
            dependency.doSomethingElse(anyInt);
            collaborator.simpleOperation(0, null, null);
         }
      };
   }

   @Test
   public void dynamicallyMockJREClass()
   {
      final List<String> list = new LinkedList<String>();

      new NonStrictExpectations(list)
      {
         {
            list.get(1); result = "an item";
            list.size(); result = 2;
         }
      };

      // Use mocked methods:
      assertEquals(2, list.size());
      assertEquals("an item", list.get(1));

      // Use unmocked methods:
      assertTrue(list.add("another"));
      assertEquals("another", list.remove(0));
   }

   @Test
   public void attemptToUseDynamicMockingForInvalidTypes()
   {
      assertInvalidTypeForDynamicMocking(Dependency.class);
      assertInvalidTypeForDynamicMocking(Test.class);
      assertInvalidTypeForDynamicMocking(int[].class);
      assertInvalidTypeForDynamicMocking(new String[1]);
      assertInvalidTypeForDynamicMocking(char.class);
      assertInvalidTypeForDynamicMocking(123);
      assertInvalidTypeForDynamicMocking(Boolean.class);
      assertInvalidTypeForDynamicMocking(true);
      assertInvalidTypeForDynamicMocking(2.5);
      assertInvalidTypeForDynamicMocking(Mockit.newEmptyProxy(Dependency.class));
   }

   private void assertInvalidTypeForDynamicMocking(Object classOrObject)
   {
      try {
         new Expectations(classOrObject) {};
         fail();
      }
      catch (IllegalArgumentException ignore) {}
   }

   @Test
   public void dynamicPartialMockingWithExactArgumentMatching()
   {
      final Collaborator collaborator = new Collaborator();

      new NonStrictExpectations(collaborator)
      {{
         collaborator.simpleOperation(1, "s", null); result = false;
      }};

      assertFalse(collaborator.simpleOperation(1, "s", null));
      assertTrue(collaborator.simpleOperation(2, "s", null));
      assertTrue(collaborator.simpleOperation(1, "S", null));
      assertTrue(collaborator.simpleOperation(1, "s", new Date()));
      assertTrue(collaborator.simpleOperation(1, null, new Date()));
      assertFalse(collaborator.simpleOperation(1, "s", null));

      new FullVerifications()
      {
         {
            collaborator.simpleOperation(anyInt, null, null);
         }
      };
   }

   @Test
   public void dynamicPartialMockingWithFlexibleArgumentMatching(final Collaborator mock)
   {
      new NonStrictExpectations(mock)
      {{
         mock.simpleOperation(anyInt, withPrefix("s"), null); result = false;
      }};

      Collaborator collaborator = new Collaborator();
      assertFalse(collaborator.simpleOperation(1, "sSs", null));
      assertTrue(collaborator.simpleOperation(2, " s", null));
      assertTrue(collaborator.simpleOperation(1, "S", null));
      assertFalse(collaborator.simpleOperation(-1, "s", new Date()));
      assertTrue(collaborator.simpleOperation(1, null, null));
      assertFalse(collaborator.simpleOperation(0, "string", null));
   }

   @Test
   public void dynamicPartialMockingWithOnInstanceMatching()
   {
      final Collaborator mock = new Collaborator();

      new NonStrictExpectations(mock)
      {{
         onInstance(mock).getValue(); result = 3;
      }};

      assertEquals(3, mock.getValue());
      assertEquals(4, new Collaborator(4).getValue());

      new FullVerificationsInOrder()
      {
         {
            onInstance(mock).getValue();
            mock.getValue();
         }
      };
   }

   @Test
   public void methodWithNoRecordedExpectationCalledTwiceDuringReplay()
   {
      final Collaborator collaborator = new Collaborator(123);

      new NonStrictExpectations(collaborator) {};

      assertEquals(123, collaborator.getValue());
      assertEquals(123, collaborator.getValue());

      new FullVerifications()
      {
         {
            collaborator.getValue(); times = 2;
         }
      };
   }

   static final class TaskWithConsoleInput
   {
      boolean finished;

      void doIt()
      {
         int input = '\0';

         while (input != 'A') {
            try {
               input = System.in.read();
            }
            catch (IOException e) {
               throw new RuntimeException(e);
            }

            if (input == 'Z') {
               finished = true;
               break;
            }
         }
      }
   }

   private boolean runTaskWithTimeout(long timeoutInMillis) throws InterruptedException
   {
      final TaskWithConsoleInput task = new TaskWithConsoleInput();
      Runnable asynchronousTask = new Runnable()
      {
         public void run() { task.doIt(); }
      };

      while (!task.finished) {
         Thread worker = new Thread(asynchronousTask);
         worker.start();
         worker.join(timeoutInMillis);

         if (worker.isAlive()) {
            worker.interrupt();
            return false;
         }
      }

      return true;
   }

   @Test
   public void taskWithConsoleInputTerminatingNormally() throws Exception
   {
      new Expectations(System.in)
      {
         {
            System.in.read(); returns((int) 'A', (int) 'x', (int) 'Z');
{'fraction_non_alphanumeric': 0.10387053720387053, 'fraction_numerical': 0.008408408408408409, 'mean_word_length': 2.5493841781146376, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2759394', 'n_tokens_mistral': 8303, 'n_tokens_neox': 7921, 'n_words': 1810}