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

  This is test 'objc', covering all functions starting with 'objc'.  */

/* { dg-do run } */
/* Although this works with the NeXT runtime in a sub-set of cases, some
   versions of the runtime header pulls in a number of system protocols,
   which causes the objc_copyProtocolList test to fail (in addition to those
   systems that don't have the V2 APis).  XFAILing the run is not useful
   since it will XPASS on the sub-set that works.  */
/* { dg-skip-if "Incompatible" { *-*-darwin* } { "-fnext-runtime" } { "" } } */
// { 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

@protocol MyProtocol
- (id) variable;
@end

@protocol MySecondProtocol
- (id) setVariable: (id)value;
@end

@interface MySubClass : MyRootClass <MyProtocol>
{ id variable_ivar; }
- (void) setVariable: (id)value;
- (id) variable;
@end

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

/* Hack to calculate the log2 of a byte alignment.  */
unsigned char
log_2_of (unsigned int x)
{
  unsigned char result = 0;

  /* We count how many times we need to divide by 2 before we reach 1.
     This algorithm is good enough for the small numbers (such as 8,
     16 or 64) that we have to deal with.  */
  while (x > 1)
    {
      x = x / 2;
      result++;
    }

  return result;
}

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

  std::cout << "Testing objc_allocateClassPair ()...\n";
  {
    Class new_root_class = objc_allocateClassPair (Nil, "MyNewRootClass", 0);
    Class new_class = objc_allocateClassPair (objc_getClass ("MyRootClass"), "MyNewSubClass", 0);

    /* A new root class would obviously need at least an 'isa'
       instance variable.  */
    class_addIvar (new_root_class, "isa", sizeof (Class), log_2_of (__alignof__ (Class)),
		   @encode (Class));

    objc_registerClassPair (new_root_class);
    objc_registerClassPair (new_class);

    if (std::strcmp (class_getName (new_class), "MyNewSubClass") != 0)
      abort ();

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

    if (std::strcmp (class_getName (new_root_class), "MyNewRootClass") != 0)
      abort ();

    if (class_getSuperclass (new_root_class) != Nil)
      abort ();

    {
      MySubClass *o = [[(Class)objc_getClass ("MyNewSubClass") alloc] init];
      
      if (object_getClass (o) != objc_getClass ("MyNewSubClass"))
	abort ();
    }
  }

  std::cout << "Testing objc_copyProtocolList ()...\n";
  {
    /* Make sure both our two protocols are known to the runtime.  */
    id my_protocol = @protocol (MyProtocol);
    id my_second_protocol = @protocol (MySecondProtocol);
    unsigned int count;
    Protocol ** list = objc_copyProtocolList (&count);

    if (count != 2)
      abort ();

    if (! ((std::strcmp (protocol_getName (list[0]), "MyProtocol") == 0
	    && std::strcmp (protocol_getName (list[1]), "MySecondProtocol") == 0)
	   || (std::strcmp (protocol_getName (list[0]), "MySecondProtocol") == 0
	       && std::strcmp (protocol_getName (list[1]), "MyProtocol") == 0)))
      abort ();
    
    if (list[2] != NULL)
      abort ();
  }

  std::cout << "Testing objc_disposeClassPair ()...\n";
  {
    Method method = class_getInstanceMethod (objc_getClass ("MySubClass"), @selector (setVariable:));
    Class new_class = objc_allocateClassPair (objc_getClass ("MyRootClass"), "MyNewSubClass2", 0);

    if (new_class == Nil)
      abort ();

    /* Add a bit of everything to the class to exercise undoing all these changes.  */

    /* Instance variable.  */
    class_addIvar (new_class, "my_variable", sizeof (float), log_2_of (__alignof__ (float)), @encode (float));

    /* Instance method.  */
    class_addMethod (new_class, @selector (setVariable:), method_getImplementation (method),
		     method_getTypeEncoding (method));

    /* Class method.  */
    class_addMethod (object_getClass (new_class), @selector (setVariable:), method_getImplementation (method),
		     method_getTypeEncoding (method));

    /* Protocol.  */
    class_addProtocol (new_class, @protocol (MyProtocol));

    objc_disposeClassPair (new_class);
  }

  /* This function currently does not exist with the GNU runtime.  */
  /* std::cout << "Testing objc_duplicateClass ()...\n"; */

  /* TODO - Test it when implemented in the GNU Runtime */
  /*  std::cout << "Testing objc_getAssociatedObject ()...\n";  */

  std::cout << "Testing objc_getClass ()...\n";
  {
    if (std::strcmp (class_getName (objc_getClass ("MySubClass")),
			"MySubClass") != 0)
      abort ();
  }

  std::cout << "Testing objc_getClassList ()...\n";
  {
    Class *list;
    int i, count, other_count;
    count = objc_getClassList (NULL, 0);

    /* count most likely will be 5, (MyRootClass, MySubClass,
       Protocol, Object, NXConstantString).  */
    if (count < 3)
      abort ();
    
    list = (Class *)(malloc (sizeof (Class) * count));
    other_count = objc_getClassList (list, count);

    if (other_count != count)
      abort ();

    /* Spot-check: search for class 'MyRootClass' in the list.  */
    for (i = 0; i < count; i++)
      {
	if (std::strcmp (class_getName (list[i]), "MyRootClass") == 0)
	  break;
      }
    if (i == count)
      abort ();

    /* Spot-check: search for class 'MySubClass' in the list.  */
    for (i = 0; i < count; i++)
      {
	if (std::strcmp (class_getName (list[i]), "MySubClass") == 0)
	  break;
      }
    if (i == count)
      abort ();

    /* Spot-check: search for class 'Protocol' in the list.  */
    for (i = 0; i < count; i++)
      {
	if (std::strcmp (class_getName (list[i]), "Protocol") == 0)
	  break;
      }
    if (i == count)
      abort ();
  }

  /* This function does not exist with the GNU runtime.  */
  /* std::cout << "Testing objc_getFutureClass ()...\n"; */

  std::cout << "Testing objc_getMetaClass ()...\n";
  {
    if (! class_isMetaClass (objc_getMetaClass ("MyRootClass")))
      abort ();
  }

  std::cout << "Testing objc_getProtocol ()...\n";
  {
    if (! protocol_isEqual (objc_getProtocol ("MyProtocol"), @protocol (MyProtocol)))
      abort ();
  }

  std::cout << "Testing objc_getRequiredClass ()...\n";
  {
    if (std::strcmp (class_getName (objc_getRequiredClass ("MyRootClass")),
			"MyRootClass") != 0)
      abort ();
  }

  std::cout << "Testing objc_lookUpClass ()...\n";
  {
    if (std::strcmp (class_getName (objc_lookUpClass ("MyRootClass")),
			"MyRootClass") != 0)
      abort ();
  }

  /* This function does not exist with the GNU runtime.  */
  /* std::cout << "Testing objc_setFutureClass ()...\n"; */

  std::cout << "Testing objc_registerClassPair ()...\n";
  {
    Class new_class = objc_allocateClassPair (objc_getClass ("MySubClass"), "MySubSubClass", 0);

    class_addProtocol (new_class, @protocol (MySecondProtocol));
    
    objc_registerClassPair (new_class);
    
    if (std::strcmp (class_getName (new_class), "MySubSubClass") != 0)
      abort ();

    if (class_getSuperclass (new_class) != objc_getClass ("MySubClass"))
      abort ();

    if (! class_conformsToProtocol (new_class, @protocol (MySecondProtocol)))
      abort ();
  }

  /* TODO - Test it when implemented in the GNU Runtime */
  /*  std::cout << "Testing objc_removeAssociatedObjects ()...\n";  */

  /* TODO - Test it when implemented in the GNU Runtime */
  /*  std::cout << "Testing objc_setAssociatedObject ()...\n";  */

  return (0);
}
