Best Mockito code snippet using org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.arguments
Source:InlineDelegateByteBuddyMockMaker.java
...251 return false;252 }253 };254 ConstructionCallback onConstruction =255 (type, object, arguments, parameterTypeNames) -> {256 if (mockitoConstruction.get()) {257 Object spy = currentSpied.get();258 if (spy == null) {259 return null;260 } else if (type.isInstance(spy)) {261 return spy;262 } else {263 isSuspended.set(true);264 try {265 // Unexpected construction of non-spied object266 throw new MockitoException(267 "Unexpected spy for "268 + type.getName()269 + " on instance of "270 + object.getClass().getName(),271 object instanceof Throwable ? (Throwable) object : null);272 } finally {273 isSuspended.set(false);274 }275 }276 } else if (currentConstruction.get() != type) {277 return null;278 }279 currentConstruction.remove();280 isSuspended.set(true);281 try {282 Map<Class<?>, BiConsumer<Object, MockedConstruction.Context>> interceptors =283 mockedConstruction.get();284 if (interceptors != null) {285 BiConsumer<Object, MockedConstruction.Context> interceptor =286 interceptors.get(type);287 if (interceptor != null) {288 interceptor.accept(289 object,290 new InlineConstructionMockContext(291 arguments, object.getClass(), parameterTypeNames));292 }293 }294 } finally {295 isSuspended.set(false);296 }297 return null;298 };299 bytecodeGenerator =300 new TypeCachingBytecodeGenerator(301 new InlineBytecodeGenerator(302 INSTRUMENTATION,303 mocks,304 mockedStatics,305 isMockConstruction,306 onConstruction),307 true);308 }309 @Override310 public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {311 return doCreateMock(settings, handler, false);312 }313 @Override314 public <T> Optional<T> createSpy(315 MockCreationSettings<T> settings, MockHandler handler, T object) {316 if (object == null) {317 throw new MockitoConfigurationException("Spy instance must not be null");318 }319 currentSpied.set(object);320 try {321 return Optional.ofNullable(doCreateMock(settings, handler, true));322 } finally {323 currentSpied.remove();324 }325 }326 private <T> T doCreateMock(327 MockCreationSettings<T> settings,328 MockHandler handler,329 boolean nullOnNonInlineConstruction) {330 Class<? extends T> type = createMockType(settings);331 try {332 T instance;333 if (settings.isUsingConstructor()) {334 instance =335 new ConstructorInstantiator(336 settings.getOuterClassInstance() != null,337 settings.getConstructorArgs())338 .newInstance(type);339 } else {340 try {341 // We attempt to use the "native" mock maker first that avoids342 // Objenesis and Unsafe343 instance = newInstance(type);344 } catch (InstantiationException ignored) {345 if (nullOnNonInlineConstruction) {346 return null;347 }348 Instantiator instantiator =349 Plugins.getInstantiatorProvider().getInstantiator(settings);350 instance = instantiator.newInstance(type);351 }352 }353 MockMethodInterceptor mockMethodInterceptor =354 new MockMethodInterceptor(handler, settings);355 mocks.put(instance, mockMethodInterceptor);356 if (instance instanceof MockAccess) {357 ((MockAccess) instance).setMockitoInterceptor(mockMethodInterceptor);358 }359 return instance;360 } catch (InstantiationException e) {361 throw new MockitoException(362 "Unable to create mock instance of type '" + type.getSimpleName() + "'", e);363 }364 }365 @Override366 public <T> Class<? extends T> createMockType(MockCreationSettings<T> settings) {367 try {368 return bytecodeGenerator.mockClass(369 MockFeatures.withMockFeatures(370 settings.getTypeToMock(),371 settings.getExtraInterfaces(),372 settings.getSerializableMode(),373 settings.isStripAnnotations(),374 settings.getDefaultAnswer()));375 } catch (Exception bytecodeGenerationFailed) {376 throw prettifyFailure(settings, bytecodeGenerationFailed);377 }378 }379 private <T> RuntimeException prettifyFailure(380 MockCreationSettings<T> mockFeatures, Exception generationFailed) {381 if (mockFeatures.getTypeToMock().isArray()) {382 throw new MockitoException(383 join("Arrays cannot be mocked: " + mockFeatures.getTypeToMock() + ".", ""),384 generationFailed);385 }386 if (Modifier.isFinal(mockFeatures.getTypeToMock().getModifiers())) {387 throw new MockitoException(388 join(389 "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",390 "Can not mock final classes with the following settings :",391 " - explicit serialization (e.g. withSettings().serializable())",392 " - extra interfaces (e.g. withSettings().extraInterfaces(...))",393 "",394 "You are seeing this disclaimer because Mockito is configured to create inlined mocks.",395 "You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.",396 "",397 "Underlying exception : " + generationFailed),398 generationFailed);399 }400 if (Modifier.isPrivate(mockFeatures.getTypeToMock().getModifiers())) {401 throw new MockitoException(402 join(403 "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",404 "Most likely it is a private class that is not visible by Mockito",405 "",406 "You are seeing this disclaimer because Mockito is configured to create inlined mocks.",407 "You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.",408 ""),409 generationFailed);410 }411 throw new MockitoException(412 join(413 "Mockito cannot mock this class: " + mockFeatures.getTypeToMock() + ".",414 "",415 "If you're not sure why you're getting this error, please report to the mailing list.",416 "",417 Platform.warnForVM(418 "IBM J9 VM",419 "Early IBM virtual machine are known to have issues with Mockito, please upgrade to an up-to-date version.\n",420 "Hotspot",421 Platform.isJava8BelowUpdate45()422 ? "Java 8 early builds have bugs that were addressed in Java 1.8.0_45, please update your JDK!\n"423 : ""),424 Platform.describe(),425 "",426 "You are seeing this disclaimer because Mockito is configured to create inlined mocks.",427 "You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.",428 "",429 "Underlying exception : " + generationFailed),430 generationFailed);431 }432 @Override433 public MockHandler getHandler(Object mock) {434 MockMethodInterceptor interceptor;435 if (mock instanceof Class<?>) {436 Map<Class<?>, MockMethodInterceptor> interceptors = mockedStatics.get();437 interceptor = interceptors != null ? interceptors.get(mock) : null;438 } else {439 interceptor = mocks.get(mock);440 }441 if (interceptor == null) {442 return null;443 } else {444 return interceptor.handler;445 }446 }447 @Override448 public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {449 MockMethodInterceptor mockMethodInterceptor =450 new MockMethodInterceptor(newHandler, settings);451 if (mock instanceof Class<?>) {452 Map<Class<?>, MockMethodInterceptor> interceptors = mockedStatics.get();453 if (interceptors == null || !interceptors.containsKey(mock)) {454 throw new MockitoException(455 "Cannot reset "456 + mock457 + " which is not currently registered as a static mock");458 }459 interceptors.put((Class<?>) mock, mockMethodInterceptor);460 } else {461 if (!mocks.containsKey(mock)) {462 throw new MockitoException(463 "Cannot reset " + mock + " which is not currently registered as a mock");464 }465 mocks.put(mock, mockMethodInterceptor);466 if (mock instanceof MockAccess) {467 ((MockAccess) mock).setMockitoInterceptor(mockMethodInterceptor);468 }469 }470 }471 @Override472 public void clearAllCaches() {473 clearAllMocks();474 bytecodeGenerator.clearAllCaches();475 }476 @Override477 public void clearMock(Object mock) {478 if (mock instanceof Class<?>) {479 for (Map<Class<?>, ?> entry : mockedStatics.getBackingMap().target.values()) {480 entry.remove(mock);481 }482 } else {483 mocks.remove(mock);484 }485 }486 @Override487 public void clearAllMocks() {488 mockedStatics.getBackingMap().clear();489 mocks.clear();490 }491 @Override492 public TypeMockability isTypeMockable(final Class<?> type) {493 return new TypeMockability() {494 @Override495 public boolean mockable() {496 return INSTRUMENTATION.isModifiableClass(type) && !EXCLUDES.contains(type);497 }498 @Override499 public String nonMockableReason() {500 if (mockable()) {501 return "";502 }503 if (type.isPrimitive()) {504 return "primitive type";505 }506 if (EXCLUDES.contains(type)) {507 return "Cannot mock wrapper types, String.class or Class.class";508 }509 return "VM does not support modification of given type";510 }511 };512 }513 @Override514 public <T> StaticMockControl<T> createStaticMock(515 Class<T> type, MockCreationSettings<T> settings, MockHandler handler) {516 if (type == ConcurrentHashMap.class) {517 throw new MockitoException(518 "It is not possible to mock static methods of ConcurrentHashMap "519 + "to avoid infinitive loops within Mockito's implementation of static mock handling");520 } else if (type == Thread.class521 || type == System.class522 || type == Arrays.class523 || ClassLoader.class.isAssignableFrom(type)) {524 throw new MockitoException(525 "It is not possible to mock static methods of "526 + type.getName()527 + " to avoid interfering with class loading what leads to infinite loops");528 }529 bytecodeGenerator.mockClassStatic(type);530 Map<Class<?>, MockMethodInterceptor> interceptors = mockedStatics.get();531 if (interceptors == null) {532 interceptors = new WeakHashMap<>();533 mockedStatics.set(interceptors);534 }535 return new InlineStaticMockControl<>(type, interceptors, settings, handler);536 }537 @Override538 public <T> ConstructionMockControl<T> createConstructionMock(539 Class<T> type,540 Function<MockedConstruction.Context, MockCreationSettings<T>> settingsFactory,541 Function<MockedConstruction.Context, MockHandler<T>> handlerFactory,542 MockedConstruction.MockInitializer<T> mockInitializer) {543 if (type == Object.class) {544 throw new MockitoException(545 "It is not possible to mock construction of the Object class "546 + "to avoid inference with default object constructor chains");547 } else if (type.isPrimitive() || Modifier.isAbstract(type.getModifiers())) {548 throw new MockitoException(549 "It is not possible to construct primitive types or abstract types: "550 + type.getName());551 }552 bytecodeGenerator.mockClassConstruction(type);553 Map<Class<?>, BiConsumer<Object, MockedConstruction.Context>> interceptors =554 mockedConstruction.get();555 if (interceptors == null) {556 interceptors = new WeakHashMap<>();557 mockedConstruction.set(interceptors);558 }559 return new InlineConstructionMockControl<>(560 type, settingsFactory, handlerFactory, mockInitializer, interceptors);561 }562 @Override563 @SuppressWarnings("unchecked")564 public <T> T newInstance(Class<T> cls) throws InstantiationException {565 Constructor<?>[] constructors = cls.getDeclaredConstructors();566 if (constructors.length == 0) {567 throw new InstantiationException(cls.getName() + " does not define a constructor");568 }569 Constructor<?> selected = constructors[0];570 for (Constructor<?> constructor : constructors) {571 if (Modifier.isPublic(constructor.getModifiers())) {572 selected = constructor;573 break;574 }575 }576 Class<?>[] types = selected.getParameterTypes();577 Object[] arguments = new Object[types.length];578 int index = 0;579 for (Class<?> type : types) {580 arguments[index++] = makeStandardArgument(type);581 }582 MemberAccessor accessor = Plugins.getMemberAccessor();583 try {584 return (T)585 accessor.newInstance(586 selected,587 callback -> {588 mockitoConstruction.set(true);589 try {590 return callback.newInstance();591 } finally {592 mockitoConstruction.set(false);593 }594 },595 arguments);596 } catch (Exception e) {597 throw new InstantiationException("Could not instantiate " + cls.getName(), e);598 }599 }600 private Object makeStandardArgument(Class<?> type) {601 if (type == boolean.class) {602 return false;603 } else if (type == byte.class) {604 return (byte) 0;605 } else if (type == short.class) {606 return (short) 0;607 } else if (type == char.class) {608 return (char) 0;609 } else if (type == int.class) {610 return 0;611 } else if (type == long.class) {612 return 0L;613 } else if (type == float.class) {614 return 0f;615 } else if (type == double.class) {616 return 0d;617 } else {618 return null;619 }620 }621 private static class InlineStaticMockControl<T> implements StaticMockControl<T> {622 private final Class<T> type;623 private final Map<Class<?>, MockMethodInterceptor> interceptors;624 private final MockCreationSettings<T> settings;625 private final MockHandler handler;626 private InlineStaticMockControl(627 Class<T> type,628 Map<Class<?>, MockMethodInterceptor> interceptors,629 MockCreationSettings<T> settings,630 MockHandler handler) {631 this.type = type;632 this.interceptors = interceptors;633 this.settings = settings;634 this.handler = handler;635 }636 @Override637 public Class<T> getType() {638 return type;639 }640 @Override641 public void enable() {642 if (interceptors.putIfAbsent(type, new MockMethodInterceptor(handler, settings))643 != null) {644 throw new MockitoException(645 join(646 "For "647 + type.getName()648 + ", static mocking is already registered in the current thread",649 "",650 "To create a new mock, the existing static mock registration must be deregistered"));651 }652 }653 @Override654 public void disable() {655 if (interceptors.remove(type) == null) {656 throw new MockitoException(657 join(658 "Could not deregister "659 + type.getName()660 + " as a static mock since it is not currently registered",661 "",662 "To register a static mock, use Mockito.mockStatic("663 + type.getSimpleName()664 + ".class)"));665 }666 }667 }668 private class InlineConstructionMockControl<T> implements ConstructionMockControl<T> {669 private final Class<T> type;670 private final Function<MockedConstruction.Context, MockCreationSettings<T>> settingsFactory;671 private final Function<MockedConstruction.Context, MockHandler<T>> handlerFactory;672 private final MockedConstruction.MockInitializer<T> mockInitializer;673 private final Map<Class<?>, BiConsumer<Object, MockedConstruction.Context>> interceptors;674 private final List<Object> all = new ArrayList<>();675 private int count;676 private InlineConstructionMockControl(677 Class<T> type,678 Function<MockedConstruction.Context, MockCreationSettings<T>> settingsFactory,679 Function<MockedConstruction.Context, MockHandler<T>> handlerFactory,680 MockedConstruction.MockInitializer<T> mockInitializer,681 Map<Class<?>, BiConsumer<Object, MockedConstruction.Context>> interceptors) {682 this.type = type;683 this.settingsFactory = settingsFactory;684 this.handlerFactory = handlerFactory;685 this.mockInitializer = mockInitializer;686 this.interceptors = interceptors;687 }688 @Override689 public Class<T> getType() {690 return type;691 }692 @Override693 public void enable() {694 if (interceptors.putIfAbsent(695 type,696 (object, context) -> {697 ((InlineConstructionMockContext) context).count = ++count;698 MockMethodInterceptor interceptor =699 new MockMethodInterceptor(700 handlerFactory.apply(context),701 settingsFactory.apply(context));702 mocks.put(object, interceptor);703 try {704 @SuppressWarnings("unchecked")705 T cast = (T) object;706 mockInitializer.prepare(cast, context);707 } catch (Throwable t) {708 mocks.remove(object); // TODO: filter stack trace?709 throw new MockitoException(710 "Could not initialize mocked construction", t);711 }712 all.add(object);713 })714 != null) {715 throw new MockitoException(716 join(717 "For "718 + type.getName()719 + ", static mocking is already registered in the current thread",720 "",721 "To create a new mock, the existing static mock registration must be deregistered"));722 }723 }724 @Override725 public void disable() {726 if (interceptors.remove(type) == null) {727 throw new MockitoException(728 join(729 "Could not deregister "730 + type.getName()731 + " as a static mock since it is not currently registered",732 "",733 "To register a static mock, use Mockito.mockStatic("734 + type.getSimpleName()735 + ".class)"));736 }737 all.clear();738 }739 @Override740 @SuppressWarnings("unchecked")741 public List<T> getMocks() {742 return (List<T>) all;743 }744 }745 private static class InlineConstructionMockContext implements MockedConstruction.Context {746 private static final Map<String, Class<?>> PRIMITIVES = new HashMap<>();747 static {748 PRIMITIVES.put(boolean.class.getName(), boolean.class);749 PRIMITIVES.put(byte.class.getName(), byte.class);750 PRIMITIVES.put(short.class.getName(), short.class);751 PRIMITIVES.put(char.class.getName(), char.class);752 PRIMITIVES.put(int.class.getName(), int.class);753 PRIMITIVES.put(long.class.getName(), long.class);754 PRIMITIVES.put(float.class.getName(), float.class);755 PRIMITIVES.put(double.class.getName(), double.class);756 }757 private int count;758 private final Object[] arguments;759 private final Class<?> type;760 private final String[] parameterTypeNames;761 private InlineConstructionMockContext(762 Object[] arguments, Class<?> type, String[] parameterTypeNames) {763 this.arguments = arguments;764 this.type = type;765 this.parameterTypeNames = parameterTypeNames;766 }767 @Override768 public int getCount() {769 if (count == 0) {770 throw new MockitoConfigurationException(771 "mocked construction context is not initialized");772 }773 return count;774 }775 @Override776 public Constructor<?> constructor() {777 Class<?>[] parameterTypes = new Class<?>[parameterTypeNames.length];778 int index = 0;779 for (String parameterTypeName : parameterTypeNames) {780 if (PRIMITIVES.containsKey(parameterTypeName)) {781 parameterTypes[index++] = PRIMITIVES.get(parameterTypeName);782 } else {783 try {784 parameterTypes[index++] =785 Class.forName(parameterTypeName, false, type.getClassLoader());786 } catch (ClassNotFoundException e) {787 throw new MockitoException(788 "Could not find parameter of type " + parameterTypeName, e);789 }790 }791 }792 try {793 return type.getDeclaredConstructor(parameterTypes);794 } catch (NoSuchMethodException e) {795 throw new MockitoException(796 join(797 "Could not resolve constructor of type",798 "",799 type.getName(),800 "",801 "with arguments of types",802 Arrays.toString(parameterTypes)),803 e);804 }805 }806 @Override807 public List<?> arguments() {808 return Collections.unmodifiableList(Arrays.asList(arguments));809 }810 }811}...
arguments
Using AI Code Generation
1package org.mockito.internal.creation.bytebuddy;2import net.bytebuddy.ByteBuddy;3import net.bytebuddy.asm.Advice;4import net.bytebuddy.description.method.MethodDescription;5import net.bytebuddy.description.modifier.Visibility;6import net.bytebuddy.description.type.TypeDescription;7import net.bytebuddy.dynamic.DynamicType;8import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;9import net.bytebuddy.implementation.FixedValue;10import net.bytebuddy.implementation.MethodDelegation;11import net.bytebuddy.implementation.bind.annotation.Argument;12import net.bytebuddy.implementation.bind.annotation.RuntimeType;13import net.bytebuddy.implementation.bind.annotation.SuperCall;14import net.bytebuddy.matcher.ElementMatchers;15import org.mockito.internal.creation.bytebuddy.MockMethodInterceptor;16import java.lang.reflect.Method;17import java.util.concurrent.Callable;18public class InlineDelegateByteBuddyMockMaker extends ByteBuddyMockMaker {19 private static final String INLINE_DELEGATE = "inlineDelegate";20 protected DynamicType.Builder<?> prepareMock(Class<?> type, Class<?>[] interfaces) {21 DynamicType.Builder<?> builder = super.prepareMock(type, interfaces);22 if (type.isInterface()) {23 builder = builder.implement(InlineDelegate.class);24 } else {25 builder = builder.defineMethod(INLINE_DELEGATE, Object.class, Visibility.PUBLIC)26 .intercept(FixedValue.nullValue())27 .withParameter(Object.class, "delegate");28 }29 return builder;30 }31 protected MockMethodInterceptor getInterceptor(Class<?> type, Object[] arguments) {32 Object delegate = (type.isInterface() && arguments.length == 1) ? arguments[0] : null;33 return new InlineDelegateInterceptor(delegate);34 }35 public static class InlineDelegateInterceptor implements MockMethodInterceptor {36 private final Object delegate;37 public InlineDelegateInterceptor(Object delegate) {38 this.delegate = delegate;39 }40 public Object intercept(Object mock, Method method, Object[] args, Callable<?> callable) throws Throwable {41 if (INLINE_DELEGATE.equals(method.getName())) {42 return delegate;43 }44 Object delegate = this.delegate;45 if (delegate == null) {46 delegate = mock;47 }48 return method.invoke(delegate, args);49 }50 }51 public static class InlineDelegate {52 public static Object intercept(
arguments
Using AI Code Generation
1 Object mockInstance = arguments[0];2 Method method = (Method) arguments[1];3 Object[] args = (Object[]) arguments[2];4 Method delegateMethod = (Method) arguments[3];5 Object[] delegateArgs = (Object[]) arguments[4];6 Method realMethod = (Method) arguments[5];7 Object[] realMethodArgs = (Object[]) arguments[6];8 Object delegate = arguments[7];9 MethodHandle mockMethodHandle = (MethodHandle) arguments[8];10 MethodHandle delegateMethodHandle = (MethodHandle) arguments[9];11 MethodHandle realMethodHandle = (MethodHandle) arguments[10];12 MethodHandle superMethodHandle = (MethodHandle) arguments[11];13 try {14 return mockMethodHandle.invokeWithArguments(args);15 } catch (Throwable throwable) {16 throw new RuntimeException(throwable);17 }18 }19}20public class MockitoInlineDelegateTest {21 public void test() {22 Mockito.mock(List.class, new MockitoInlineDelegateMockMaker());23 }24}
arguments
Using AI Code Generation
1MockMaker mockMaker = new InlineDelegateByteBuddyMockMaker();2MockSettings mockSettings = withSettings();3MockHandler mockHandler = new MockHandlerImpl(mockSettings.getDefaultAnswer());4MockType mockType = new MockType();5Arguments arguments = new Arguments(mockSettings, mockType, mockHandler);6MockAccess mockAccess = mockMaker.createMock(arguments);7Object mock = mockAccess.getMock();8assertNotNull(mock);9assertTrue(mockType.getType().isInstance(mock));10assertEquals(mockHandler, MockUtil.getMockHandler(mock));11assertTrue(MockUtil.isMock(mock));12assertFalse(MockUtil.isSpy(mock));13assertFalse(mock instanceof Serializable);14assertFalse(MockUtil.isStubOnly(mock));15assertFalse(MockUtil.isVerifiedOnly(mock));16assertFalse(MockUtil.isDefaultAnswer(mock));17assertFalse(MockUtil.isStrict(mock));18assertFalse(MockUtil.isLenient(mock));
arguments
Using AI Code Generation
1import net.bytebuddy.ByteBuddy2import net.bytebuddy.description.modifier.Visibility3import net.bytebuddy.dynamic.DynamicType4import net.bytebuddy.dynamic.loading.ClassLoadingStrategy5import net.bytebuddy.implementation.InvocationHandlerAdapter6import net.bytebuddy.matcher.ElementMatchers7import org.mockito.Mockito.mock8public class MockMaker {9 public static <T> T makeMock(Class<T> clazz) {10 DynamicType.Unloaded<T> unloaded = new ByteBuddy()11 .subclass(clazz)12 .method(ElementMatchers.any())13 .intercept(InvocationHandlerAdapter.of(new MockMaker()))14 .make()15 .load(clazz.classLoader, ClassLoadingStrategy.Default.INJECTION)16 .getLoaded()17 .getConstructor()18 .newInstance()19 }20 public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) {21 if (method.getName().equals("toString")) {22 return "Mock for " + method.getDeclaringClass().getName()23 }24 if (method.getName().equals("hashCode")) {25 }26 if (method.getName().equals("equals")) {27 }28 if (method.getDeclaringClass().equals(Object.class)) {29 }30 return mock(method.getReturnType())31 }32}33public class Foo {34 public String bar() {35 }36}37public class Main {38 public static void main(String[] args) {39 Foo foo = MockMaker.makeMock(Foo.class)40 println foo.bar()41 }42}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!