/* Test the Modern GNU Objective-C Runtime API.

  This is test 'class-meta', covering calling functions starting with
  'class' but using a meta class as argument.

  Functions that manipulate methods (adding, replacing methods)
  usually take a meta class argument to manipulate the class methods
  instead of the instance ones.  This is an important part of the API
  that needs testing.

  Functions that manipulate instances, instance variables, properties
  and protocols at the moment must take a normal class as argument;
  calling them with a meta class as argument is of no particular use
  and generally produces a behavior that is undocumented and/or
  undefined (and this is true with all runtimes).  As in the future
  this behavior may be defined or documented (for example, if class
  variables are implemented as instance variables of meta classes) we
  avoid testing it for compatibility with future runtimes.  */

/* { dg-do run } */
/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
/* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */
// { dg-additional-options "-Wno-objc-root-class" }

/* To get the modern GNU Objective-C Runtime API, you include
   objc/runtime.h.  */
#include <objc/runtime.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>

@interface MyRootClass
{ Class isa; }
+ alloc;
- init;
+ initialize;
@end

@implementation MyRootClass
+ alloc { return class_createInstance (self, 0); }
- init  { return self; }
+ initialize { return self; }
@end

static id static_variable = nil;

@interface MySubClass : MyRootClass
+ (void) setVariable: (id)value;
+ (id) variable;
@end

@implementation MySubClass
+ (void) setVariable: (id)value { static_variable = value; }
+ (id) variable { return static_variable; }
@end

@interface DifferentClass : MyRootClass
+ (id) myClass;
@end

@implementation DifferentClass
+ (id) myClass { return self; }
@end

@interface MySubClass (MySelf)
+ (id) mySelf;
@end

int main ()
{
  /* Functions are tested in alphabetical order.  */

  /* Calling class_addIvar() with a meta class is not documented and
     (currently) of no use.  */
  /* std::cout << "Testing class_addIvar ()...\n"; */
  
  std::cout << "Testing class_addMethod () on a meta class...\n";
  {
    /* Here we test adding methods to meta classes, ie, adding class methods.  */
    Class new_class = objc_allocateClassPair (objc_getClass ("MyRootClass"), "MySubClass2", 0);
    Method method1 = class_getInstanceMethod (objc_getMetaClass ("MySubClass"), @selector (setVariable:));
    Method method2 = class_getInstanceMethod (objc_getMetaClass ("MySubClass"), @selector (variable));

    if (new_class == Nil)
      abort ();
    
    if (! class_addMethod (object_getClass (new_class), @selector (setVariable:), method_getImplementation (method1),
			   method_getTypeEncoding (method1)))
      abort ();

    if (! class_addMethod (object_getClass (new_class), @selector (variable), method_getImplementation (method2),
			   method_getTypeEncoding (method2)))
      abort ();
    
    /* Test that if the method already exists in the class,
       class_addMethod() returns NO.  */
    if (class_addMethod (object_getClass (new_class), @selector (variable), method_getImplementation (method2),
			 method_getTypeEncoding (method2)))
      abort ();
    
    objc_registerClassPair (new_class);
    
    /* Now, MySubClass2 is basically the same as MySubClass!  We'll
       use the +variable and +setVariable: methods on it.  */
    {
      Class c = objc_getClass ("MySubClass2");
      id o = [[MyRootClass alloc] init];

      [c setVariable: o];
      
      if ([c variable] != o)
	abort ();
    }
    
    /* Now, try that if you take an existing class and try to add an
       already existing method, class_addMethod returns NO.  This is
       subtly different from before, when 'new_class' was still in
       construction.  Now it's a real class and the libobjc internals
       differ between the two cases.  */
    if (class_addMethod (object_getClass (new_class), @selector (variable), method_getImplementation (method2),
			 method_getTypeEncoding (method2)))
      abort ();
  }

  /* Calling class_addProtocol() on a meta class is not documented and
     (currently) of no use.  */
  /* std::cout << "Testing class_addProtocol () on a meta class...\n"; */

  /* Calling class_conformsToProtocol() on a meta class is not
     documented and (currently) of no use.  */
  /* std::cout << "Testing class_conformsToProtocol () on a meta class...\n"; */
  
  /* Calling class_copyIvarList() on a meta class is not documented
     and (currently) of no use.  */
  /* std::cout << "Testing class_copyIvarList () on a meta class...\n"; */

  std::cout << "Testing class_copyMethodList () on a meta class...\n";
  {
    /* Test that you can copy the method list of a meta class.  They
       are the class methods of the class.  */
    unsigned int count;
    Method * list = class_copyMethodList (objc_getMetaClass ("MySubClass"), &count);

    if (count != 2)
      abort ();
    
    if (! ((std::strcmp (sel_getName (method_getName (list[0])), "variable") == 0
	    && std::strcmp (sel_getName (method_getName (list[1])), "setVariable:") == 0)
	   || (std::strcmp (sel_getName (method_getName (list[0])), "setVariable:") == 0
	       && std::strcmp (sel_getName (method_getName (list[1])), "variable") == 0)))
      abort ();
    
    if (list[2] != NULL)
      abort ();
  }

  /* Calling class_copyPropertyList() on a meta class is not
     documented and (currently) of no use.  */
  /* std::cout << "Testing class_copyPropertyList () on a meta class...\n"; */

  /* Calling class_copyProtocolList() on a meta class is not
     documented and (currently) of no use.  */
  /* std::cout << "Testing class_copyProtocolList () on a meta class...\n"; */

  /* Calling class_createInstance() on a meta class is not documented
     and (currently) of no use.  */
  /* std::cout << "Testing class_createInstance () on a meta class...\n"; */

  /* Calling class_getClassMethod () on a meta class is not documented
     and (currently) of no use.  */
  /* std::cout << "Testing class_getClassMethod () on a meta class...\n"; */

  /* Calling class_getClassVariable () on a meta class is not
     documented and (currently) of no use.  */
  /* std::cout << "Testing class_getClassVariable () on a meta class ...\n"; */

  std::cout << "Testing class_getInstanceMethod () on a meta class...\n";
  {
    /* The instance method of a meta class is the class method with
       the same name of the class. */
    Method method_1 = class_getInstanceMethod (objc_getMetaClass ("MySubClass"),
					       @selector(variable));
    Method method_2 = class_getClassMethod (objc_getClass ("MySubClass"),
					    @selector(variable));
    
    if (method_1 == NULL || method_2 == NULL)
      abort ();

    if (method_1 != method_2)
      abort ();

    if (std::strcmp (sel_getName (method_getName (method_1)), "variable") != 0)
      abort ();
  }

  /* Calling class_getInstanceSize() with a meta class is not
     documented and (currently) of no use.  */
  /* std::cout << "Testing class_getInstanceSize () on a meta class...\n"; */

  /* Calling class_getInstanceVariable() with a meta class is not
     documented and (currently) of no use.  */
  /* std::cout << "Testing class_getInstanceVariable () on a meta class...\n"; */

  /* Calling class_getIvarLayout() with a meta class is not documented
     and (currently) of no use.  */
  /* std::cout << "Testing class_getIvarLayout () on a meta class...\n"; */

  std::cout << "Testing class_getMethodImplementation () on a meta class...\n";
  {
    /* Getting the method implementation with a meta class returns a
       class method.  */
    MySubClass *object = [[MySubClass alloc] init];
    IMP imp = class_getMethodImplementation (objc_getMetaClass ("MySubClass"), 
					     @selector(variable));

    if (imp == NULL)
      abort ();

    [MySubClass setVariable: object];

    if ((*imp)(objc_getClass ("MySubClass"), @selector(variable)) != object)
      abort ();
  }

  /* This function does not exist with the GNU runtime.  */
  /* std::cout << "Testing class_getMethodImplementation_stret () on a meta class...\n"; */

  std::cout << "Testing class_getName () on a meta class...\n";
  {
    /* Traditionally, a meta class has the same name as the class.  */
    if (std::strcmp (class_getName (objc_getMetaClass ("MyRootClass")),
		     "MyRootClass") != 0)
      abort ();
  }

  /* Calling class_getProperty() with a meta class is not documented
     and (currently) of no use.  */
  /* std::cout << "Testing class_getProperty ()...\n"; */

  std::cout << "Testing class_getSuperclass () on a meta class...\n";
  {
    /* The superclass of a meta class is the meta class of the superclass.  */
    if (class_getSuperclass (objc_getMetaClass ("MySubClass")) != objc_getMetaClass ("MyRootClass"))
      abort ();

    /* Test that it works on a newly created, but not registered, class.  */
    {
      Class new_class = objc_allocateClassPair (objc_getClass ("MyRootClass"), "MySubClass3", 0);

      if (class_getSuperclass (object_getClass (new_class)) != object_getClass (objc_getClass ("MyRootClass")))
	abort ();
    }
  }

  /* Calling class_getVersion() with a meta class is not documented
     and (currently) of no use.  */
  /* std::cout << "Testing class_getVersion ()...\n"; */

  /* Calling class_getWeakIvarLayout() with a meta class is not
     documented and (currently) of no use.  */
  /* std::cout << "Testing class_getWeakIvarLayout () on a meta class...\n"; */

  /* class_isMetaClass() is already tested in gnu-api-2-class.m  */
  /* std::cout << "Testing class_isMetaClass ()...\n"; */

  std::cout << "Testing class_replaceMethod () on a meta class...\n";
  {
    /* We are going to replace the [MySubclass +variable] method with
       the [DifferentClass +myClass] one.  */
    Method new_method = class_getClassMethod (objc_getClass ("DifferentClass"),
					      @selector (myClass));
    Method old_method = class_getClassMethod (objc_getClass ("MySubClass"),
					      @selector (variable));
    const char *new_types = method_getTypeEncoding (new_method);
    IMP new_imp = method_getImplementation (new_method);
    const char *old_types = method_getTypeEncoding (old_method);
    IMP old_imp = class_replaceMethod (objc_getMetaClass ("MySubClass"), @selector (variable),
				       method_getImplementation (new_method),
				       method_getTypeEncoding (new_method));
    id o = [[MyRootClass alloc] init];

    [MySubClass setVariable: o];

    /* Try the new method implementation.  */
    if ([MySubClass variable] != objc_getClass ("MySubClass"))
      abort ();

    /* Put the original method back.  */
    class_replaceMethod (objc_getMetaClass ("MySubClass"), @selector (variable),
			 old_imp, old_types);

    /* Test it's back to what it was.  */
    if ([MySubClass variable] != o)
      abort ();

    {
      /* Finally, try adding a new method.  */
      class_replaceMethod (objc_getMetaClass ("DifferentClass"), @selector (mySelf),
			   new_imp, new_types);
      
      if ([(Class)objc_getClass ("DifferentClass") mySelf] != objc_getClass ("DifferentClass"))
	abort ();
    }
  }

  std::cout << "Testing class_respondsToSelector () on a meta class...\n";
  {
    /* A meta class responds to a selector if and only if the class
       responds to the corresponding class method.  */
    if (! class_respondsToSelector (objc_getMetaClass ("MySubClass"), @selector(setVariable:)))
      abort ();

    if (class_respondsToSelector (objc_getMetaClass ("MyRootClass"), @selector(setVariable:)))
      abort ();
  }

  /* This is not really implemented with the GNU runtime.  */
  /* std::cout << "Testing class_setIvarLayout () on a meta class...\n"; */

  /* Calling class_setVersion() with a meta class is not documented
     and (currently) of no use.  */
  /* std::cout << "Testing class_setVersion () on a meta class...\n"; */

  /* This is not really implemented with the GNU runtime.  */
  /* std::cout << "Testing class_setWeakIvarLayout () on a meta class...\n"; */

return (0);
}
