/* SPDX-License-Identifier: GPL-2.0+ */ /*------------------------------------------------------------------------ . smc91111.h - macros for the LAN91C111 Ethernet Driver . . (C) Copyright 2002 . Sysgo Real-Time Solutions, GmbH . Rolf Offermanns . Copyright (C) 2001 Standard Microsystems Corporation (SMSC) . Developed by Simple Network Magic Corporation (SNMC) . Copyright (C) 1996 by Erik Stahlman (ES) . . This file contains register information and access macros for . the LAN91C111 single chip ethernet controller. It is a modified . version of the smc9194.h file. . . Information contained in this file was obtained from the LAN91C111 . manual from SMC. To get a copy, if you really want one, you can find . information under www.smsc.com. . . Authors . Erik Stahlman ( erik@vt.edu ) . Daris A Nevil ( dnevil@snmc.com ) . . History . 03/16/01 Daris A Nevil Modified for use with LAN91C111 device . ---------------------------------------------------------------------------*/ #ifndef _SMC91111_H_ #define _SMC91111_H_ #include #include /* * This function may be called by the board specific initialisation code * in order to override the default mac address. */ void smc_set_mac_addr (const unsigned char *addr); /* I want some simple types */ typedef unsigned char byte; typedef unsigned short word; typedef unsigned long int dword; struct smc91111_priv{ u8 dev_num; }; /* . DEBUGGING LEVELS . . 0 for normal operation . 1 for slightly more details . >2 for various levels of increasingly useless information . 2 for interrupt tracking, status flags . 3 for packet info . 4 for complete packet dumps */ /*#define SMC_DEBUG 0 */ /* Because of bank switching, the LAN91xxx uses only 16 I/O ports */ #define SMC_IO_EXTENT 16 #ifdef CONFIG_CPU_PXA25X #ifdef CONFIG_XSENGINE #define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+((r)<<1)))) #define SMC_inw(a,r) (*((volatile word *)((a)->iobase+((r)<<1)))) #define SMC_inb(a,p) ({ \ unsigned int __p = (unsigned int)((a)->iobase + ((p)<<1)); \ unsigned int __v = *(volatile unsigned short *)((__p) & ~2); \ if (__p & 2) __v >>= 8; \ else __v &= 0xff; \ __v; }) #else #define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+(r)))) #define SMC_inw(a,r) (*((volatile word *)((a)->iobase+(r)))) #define SMC_inb(a,p) ({ \ unsigned int __p = (unsigned int)((a)->iobase + (p)); \ unsigned int __v = *(volatile unsigned short *)((__p) & ~1); \ if (__p & 1) __v >>= 8; \ else __v &= 0xff; \ __v; }) #endif #ifdef CONFIG_XSENGINE #define SMC_outl(a,d,r) (*((volatile dword *)((a)->iobase+(r<<1))) = d) #define SMC_outw(a,d,r) (*((volatile word *)((a)->iobase+(r<<1))) = d) #else #define SMC_outl(a,d,r) (*((volatile dword *)((a)->iobase+(r))) = d) #define SMC_outw(a,d,r) (*((volatile word *)((a)->iobase+(r))) = d) #endif #define SMC_outb(a,d,r) ({ word __d = (byte)(d); \ word __w = SMC_inw((a),(r)&~1); \ __w &= ((r)&1) ? 0x00FF : 0xFF00; \ __w |= ((r)&1) ? __d<<8 : __d; \ SMC_outw((a),__w,(r)&~1); \ }) #define SMC_outsl(a,r,b,l) ({ int __i; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ SMC_outl((a), *(__b2 + __i), r); \ } \ }) #define SMC_outsw(a,r,b,l) ({ int __i; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ SMC_outw((a), *(__b2 + __i), r); \ } \ }) #define SMC_insl(a,r,b,l) ({ int __i ; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inl((a),(r)); \ SMC_inl((a),0); \ }; \ }) #define SMC_insw(a,r,b,l) ({ int __i ; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inw((a),(r)); \ SMC_inw((a),0); \ }; \ }) #define SMC_insb(a,r,b,l) ({ int __i ; \ byte *__b2; \ __b2 = (byte *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inb((a),(r)); \ SMC_inb((a),0); \ }; \ }) #elif defined(CONFIG_LEON) /* if not CONFIG_CPU_PXA25X */ #define SMC_LEON_SWAP16(_x_) ({ word _x = (_x_); ((_x << 8) | (_x >> 8)); }) #define SMC_LEON_SWAP32(_x_) \ ({ dword _x = (_x_); \ ((_x << 24) | \ ((0x0000FF00UL & _x) << 8) | \ ((0x00FF0000UL & _x) >> 8) | \ (_x >> 24)); }) #define SMC_inl(a,r) (SMC_LEON_SWAP32((*(volatile dword *)((a)->iobase+((r)<<0))))) #define SMC_inl_nosw(a,r) ((*(volatile dword *)((a)->iobase+((r)<<0)))) #define SMC_inw(a,r) (SMC_LEON_SWAP16((*(volatile word *)((a)->iobase+((r)<<0))))) #define SMC_inw_nosw(a,r) ((*(volatile word *)((a)->iobase+((r)<<0)))) #define SMC_inb(a,p) ({ \ word ___v = SMC_inw((a),(p) & ~1); \ if ((p) & 1) ___v >>= 8; \ else ___v &= 0xff; \ ___v; }) #define SMC_outl(a,d,r) (*(volatile dword *)((a)->iobase+((r)<<0))=SMC_LEON_SWAP32(d)) #define SMC_outl_nosw(a,d,r) (*(volatile dword *)((a)->iobase+((r)<<0))=(d)) #define SMC_outw(a,d,r) (*(volatile word *)((a)->iobase+((r)<<0))=SMC_LEON_SWAP16(d)) #define SMC_outw_nosw(a,d,r) (*(volatile word *)((a)->iobase+((r)<<0))=(d)) #define SMC_outb(a,d,r) do{ word __d = (byte)(d); \ word __w = SMC_inw((a),(r)&~1); \ __w &= ((r)&1) ? 0x00FF : 0xFF00; \ __w |= ((r)&1) ? __d<<8 : __d; \ SMC_outw((a),__w,(r)&~1); \ }while(0) #define SMC_outsl(a,r,b,l) do{ int __i; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ SMC_outl_nosw((a), *(__b2 + __i), r); \ } \ }while(0) #define SMC_outsw(a,r,b,l) do{ int __i; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ SMC_outw_nosw((a), *(__b2 + __i), r); \ } \ }while(0) #define SMC_insl(a,r,b,l) do{ int __i ; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inl_nosw((a),(r)); \ }; \ }while(0) #define SMC_insw(a,r,b,l) do{ int __i ; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inw_nosw((a),(r)); \ }; \ }while(0) #define SMC_insb(a,r,b,l) do{ int __i ; \ byte *__b2; \ __b2 = (byte *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inb((a),(r)); \ }; \ }while(0) #elif defined(CONFIG_MS7206SE) #define SWAB7206(x) ({ word __x = x; ((__x << 8)|(__x >> 8)); }) #define SMC_inw(a, r) *((volatile word*)((a)->iobase + (r))) #define SMC_inb(a, r) (*((volatile byte*)((a)->iobase + ((r) ^ 0x01)))) #define SMC_insw(a, r, b, l) \ do { \ int __i; \ word *__b2 = (word *)(b); \ for (__i = 0; __i < (l); __i++) { \ *__b2++ = SWAB7206(SMC_inw(a, r)); \ } \ } while (0) #define SMC_outw(a, d, r) (*((volatile word *)((a)->iobase+(r))) = d) #define SMC_outb(a, d, r) ({ word __d = (byte)(d); \ word __w = SMC_inw((a), ((r)&(~1))); \ if (((r) & 1)) \ __w = (__w & 0x00ff) | (__d << 8); \ else \ __w = (__w & 0xff00) | (__d); \ SMC_outw((a), __w, ((r)&(~1))); \ }) #define SMC_outsw(a, r, b, l) \ do { \ int __i; \ word *__b2 = (word *)(b); \ for (__i = 0; __i < (l); __i++) { \ SMC_outw(a, SWAB7206(*__b2), r); \ __b2++; \ } \ } while (0) #else /* if not CONFIG_CPU_PXA25X and not CONFIG_LEON */ #ifndef CONFIG_SMC_USE_IOFUNCS /* these macros don't work on some boards */ /* * We have only 16 Bit PCMCIA access on Socket 0 */ #ifdef CONFIG_ADNPESC1 #define SMC_inw(a,r) (*((volatile word *)((a)->iobase+((r)<<1)))) #elif CONFIG_ARM64 #define SMC_inw(a, r) (*((volatile word*)((a)->iobase+((dword)(r))))) #else #define SMC_inw(a, r) (*((volatile word*)((a)->iobase+(r)))) #endif #define SMC_inb(a,r) (((r)&1) ? SMC_inw((a),(r)&~1)>>8 : SMC_inw((a),(r)&0xFF)) #ifdef CONFIG_ADNPESC1 #define SMC_outw(a,d,r) (*((volatile word *)((a)->iobase+((r)<<1))) = d) #elif CONFIG_ARM64 #define SMC_outw(a, d, r) \ (*((volatile word*)((a)->iobase+((dword)(r)))) = d) #else #define SMC_outw(a, d, r) \ (*((volatile word*)((a)->iobase+(r))) = d) #endif #define SMC_outb(a,d,r) ({ word __d = (byte)(d); \ word __w = SMC_inw((a),(r)&~1); \ __w &= ((r)&1) ? 0x00FF : 0xFF00; \ __w |= ((r)&1) ? __d<<8 : __d; \ SMC_outw((a),__w,(r)&~1); \ }) #if 0 #define SMC_outsw(a,r,b,l) outsw((a)->iobase+(r), (b), (l)) #else #define SMC_outsw(a,r,b,l) ({ int __i; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ SMC_outw((a), *(__b2 + __i), r); \ } \ }) #endif #if 0 #define SMC_insw(a,r,b,l) insw((a)->iobase+(r), (b), (l)) #else #define SMC_insw(a,r,b,l) ({ int __i ; \ word *__b2; \ __b2 = (word *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inw((a),(r)); \ SMC_inw((a),0); \ }; \ }) #endif #endif /* CONFIG_SMC_USE_IOFUNCS */ #if defined(CONFIG_SMC_USE_32_BIT) #ifdef CONFIG_XSENGINE #define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+(r<<1)))) #else #define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+(r)))) #endif #define SMC_insl(a,r,b,l) ({ int __i ; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ *(__b2 + __i) = SMC_inl((a),(r)); \ SMC_inl((a),0); \ }; \ }) #ifdef CONFIG_XSENGINE #define SMC_outl(a,d,r) (*((volatile dword *)((a)->iobase+(r<<1))) = d) #else #define SMC_outl(a,d,r) (*((volatile dword *)((a)->iobase+(r))) = d) #endif #define SMC_outsl(a,r,b,l) ({ int __i; \ dword *__b2; \ __b2 = (dword *) b; \ for (__i = 0; __i < l; __i++) { \ SMC_outl((a), *(__b2 + __i), r); \ } \ }) #endif /* CONFIG_SMC_USE_32_BIT */ #endif /*--------------------------------------------------------------- . . A description of the SMSC registers is probably in order here, . although for details, the SMC datasheet is invaluable. . . Basically, the chip has 4 banks of registers ( 0 to 3 ), which . are accessed by writing a number into the BANK_SELECT register . ( I also use a SMC_SELECT_BANK macro for this ). . . The banks are configured so that for most purposes, bank 2 is all . that is needed for simple run time tasks. -----------------------------------------------------------------------*/ /* . Bank Select Register: . . yyyy yyyy 0000 00xx . xx = bank number . yyyy yyyy = 0x33, for identification purposes. */ #define BANK_SELECT 14 /* Transmit Control Register */ /* BANK 0 */ #define TCR_REG 0x0000 /* transmit control register */ #define TCR_ENABLE 0x0001 /* When 1 we can transmit */ #define TCR_LOOP 0x0002 /* Controls output pin LBK */ #define TCR_FORCOL 0x0004 /* When 1 will force a collision */ #define TCR_PAD_EN 0x0080 /* When 1 will pad tx frames < 64 bytes w/0 */ #define TCR_NOCRC 0x0100 /* When 1 will not append CRC to tx frames */ #define TCR_MON_CSN 0x0400 /* When 1 tx monitors carrier */ #define TCR_FDUPLX 0x0800 /* When 1 enables full duplex operation */ #define TCR_STP_SQET 0x1000 /* When 1 stops tx if Signal Quality Error */ #define TCR_EPH_LOOP 0x2000 /* When 1 enables EPH block loopback */ #define TCR_SWFDUP 0x8000 /* When 1 enables Switched Full Duplex mode */ #define TCR_CLEAR 0 /* do NOTHING */ /* the default settings for the TCR register : */ /* QUESTION: do I want to enable padding of short packets ? */ #define TCR_DEFAULT TCR_ENABLE /* EPH Status Register */ /* BANK 0 */ #define EPH_STATUS_REG 0x0002 #define ES_TX_SUC 0x0001 /* Last TX was successful */ #define ES_SNGL_COL 0x0002 /* Single collision detected for last tx */ #define ES_MUL_COL 0x0004 /* Multiple collisions detected for last tx */ #define ES_LTX_MULT 0x0008 /* Last tx was a multicast */ #define ES_16COL 0x0010 /* 16 Collisions Reached */ #define ES_SQET 0x0020 /* Signal Quality Error Test */ #define ES_LTXBRD 0x0040 /* Last tx was a broadcast */ #define ES_TXDEFR 0x0080 /* Transmit Deferred */ #define ES_LATCOL 0x0200 /* Late collision detected on last tx */ #define ES_LOSTCARR 0x0400 /* Lost Carrier Sense */ #define ES_EXC_DEF 0x0800 /* Excessive Deferral */ #define ES_CTR_ROL 0x1000 /* Counter Roll Over indication */ #define ES_LINK_OK 0x4000 /* Driven by inverted value of nLNK pin */ #define ES_TXUNRN 0x8000 /* Tx Underrun */ /* Receive Control Register */ /* BANK 0 */ #define RCR_REG 0x0004 #define RCR_RX_ABORT 0x0001 /* Set if a rx frame was aborted */ #define RCR_PRMS 0x0002 /* Enable promiscuous mode */ #define RCR_ALMUL 0x0004 /* When set accepts all multicast frames */ #define RCR_RXEN 0x0100 /* IFF this is set, we can receive packets */ #define RCR_STRIP_CRC 0x0200 /* When set strips CRC from rx packets */ #define RCR_ABORT_ENB 0x0200 /* When set will abort rx on collision */ #define RCR_FILT_CAR 0x0400 /* When set filters leading 12 bit s of carrier */ #define RCR_SOFTRST 0x8000 /* resets the chip */ /* the normal settings for the RCR register : */ #define RCR_DEFAULT (RCR_STRIP_CRC | RCR_RXEN) #define RCR_CLEAR 0x0 /* set it to a base state */ /* Counter Register */ /* BANK 0 */ #define COUNTER_REG 0x0006 /* Memory Information Register */ /* BANK 0 */ #define MIR_REG 0x0008 /* Receive/Phy Control Register */ /* BANK 0 */ #define RPC_REG 0x000A #define RPC_SPEED 0x2000 /* When 1 PHY is in 100Mbps mode. */ #define RPC_DPLX 0x1000 /* When 1 PHY is in Full-Duplex Mode */ #define RPC_ANEG 0x0800 /* When 1 PHY is in Auto-Negotiate Mode */ #define RPC_LSXA_SHFT 5 /* Bits to shift LS2A,LS1A,LS0A to lsb */ #define RPC_LSXB_SHFT 2 /* Bits to get LS2B,LS1B,LS0B to lsb */ #define RPC_LED_100_10 (0x00) /* LED = 100Mbps OR's with 10Mbps link detect */ #define RPC_LED_RES (0x01) /* LED = Reserved */ #define RPC_LED_10 (0x02) /* LED = 10Mbps link detect */ #define RPC_LED_FD (0x03) /* LED = Full Duplex Mode */ #define RPC_LED_TX_RX (0x04) /* LED = TX or RX packet occurred */ #define RPC_LED_100 (0x05) /* LED = 100Mbps link dectect */ #define RPC_LED_TX (0x06) /* LED = TX packet occurred */ #define RPC_LED_RX (0x07) /* LED = RX packet occurred */ #if defined(CONFIG_DK1C20) || defined(CONFIG_DK1S10) /* buggy schematic: LEDa -> yellow, LEDb --> green */ #define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ | (RPC_LED_TX_RX << RPC_LSXA_SHFT) \ | (RPC_LED_100_10 << RPC_LSXB_SHFT) ) #elif defined(CONFIG_ADNPESC1) /* SSV ADNP/ESC1 has only one LED: LEDa -> Rx/Tx indicator */ #define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ | (RPC_LED_TX_RX << RPC_LSXA_SHFT) \ | (RPC_LED_100_10 << RPC_LSXB_SHFT) ) #else /* SMSC reference design: LEDa --> green, LEDb --> yellow */ #define RPC_DEFAULT ( RPC_SPEED | RPC_DPLX | RPC_ANEG \ | (RPC_LED_100_10 << RPC_LSXA_SHFT) \ | (RPC_LED_TX_RX << RPC_LSXB_SHFT) ) #endif /* Bank 0 0x000C is reserved */ /* Bank Select Register */ /* All Banks */ #define BSR_REG 0x000E /* Configuration Reg */ /* BANK 1 */ #define CONFIG_REG 0x0000 #define CONFIG_EXT_PHY 0x0200 /* 1=external MII, 0=internal Phy */ #define CONFIG_GPCNTRL 0x0400 /* Inverse value drives pin nCNTRL */ #define CONFIG_NO_WAIT 0x1000 /* When 1 no extra wait states on ISA bus */ #define CONFIG_EPH_POWER_EN 0x8000 /* When 0 EPH is placed into low power mode. */ /* Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low */ #define CONFIG_DEFAULT (CONFIG_EPH_POWER_EN) /* Base Address Register */ /* BANK 1 */ #define BASE_REG 0x0002 /* Individual Address Registers */ /* BANK 1 */ #define ADDR0_REG 0x0004 #define ADDR1_REG 0x0006 #define ADDR2_REG 0x0008 /* General Purpose Register */ /* BANK 1 */ #define GP_REG 0x000A /* Control Register */ /* BANK 1 */ #define CTL_REG 0x000C #define CTL_RCV_BAD 0x4000 /* When 1 bad CRC packets are received */ #define CTL_AUTO_RELEASE 0x0800 /* When 1 tx pages are released automatically */ #define CTL_LE_ENABLE 0x0080 /* When 1 enables Link Error interrupt */ #define CTL_CR_ENABLE 0x0040 /* When 1 enables Counter Rollover interrupt */ #define CTL_TE_ENABLE 0x0020 /* When 1 enables Transmit Error interrupt */ #define CTL_EEPROM_SELECT 0x0004 /* Controls EEPROM reload & store */ #define CTL_RELOAD 0x0002 /* When set reads EEPROM into registers */ #define CTL_STORE 0x0001 /* When set stores registers into EEPROM */ #define CTL_DEFAULT (0x1A10) /* Autorelease enabled*/ /* MMU Command Register */ /* BANK 2 */ #define MMU_CMD_REG 0x0000 #define MC_BUSY 1 /* When 1 the last release has not completed */ #define MC_NOP (0<<5) /* No Op */ #define MC_ALLOC (1<<5) /* OR with number of 256 byte packets */ #define MC_RESET (2<<5) /* Reset MMU to initial state */ #define MC_REMOVE (3<<5) /* Remove the current rx packet */ #define MC_RELEASE (4<<5) /* Remove and release the current rx packet */ #define MC_FREEPKT (5<<5) /* Release packet in PNR register */ #define MC_ENQUEUE (6<<5) /* Enqueue the packet for transmit */ #define MC_RSTTXFIFO (7<<5) /* Reset the TX FIFOs */ /* Packet Number Register */ /* BANK 2 */ #define PN_REG 0x0002 /* Allocation Result Register */ /* BANK 2 */ #define AR_REG 0x0003 #define AR_FAILED 0x80 /* Alocation Failed */ /* RX FIFO Ports Register */ /* BANK 2 */ #define RXFIFO_REG 0x0004 /* Must be read as a word */ #define RXFIFO_REMPTY 0x8000 /* RX FIFO Empty */ /* TX FIFO Ports Register */ /* BANK 2 */ #define TXFIFO_REG RXFIFO_REG /* Must be read as a word */ #define TXFIFO_TEMPTY 0x80 /* TX FIFO Empty */ /* Pointer Register */ /* BANK 2 */ #define PTR_REG 0x0006 #define PTR_RCV 0x8000 /* 1=Receive area, 0=Transmit area */ #define PTR_AUTOINC 0x4000 /* Auto increment the pointer on each access */ #define PTR_READ 0x2000 /* When 1 the operation is a read */ #define PTR_NOTEMPTY 0x0800 /* When 1 _do not_ write fifo DATA REG */ /* Data Register */ /* BANK 2 */ #define SMC91111_DATA_REG 0x0008 /* Interrupt Status/Acknowledge Register */ /* BANK 2 */ #define SMC91111_INT_REG 0x000C /* Interrupt Mask Register */ /* BANK 2 */ #define IM_REG 0x000D #define IM_MDINT 0x80 /* PHY MI Register 18 Interrupt */ #define IM_ERCV_INT 0x40 /* Early Receive Interrupt */ #define IM_EPH_INT 0x20 /* Set by Etheret Protocol Handler section */ #define IM_RX_OVRN_INT 0x10 /* Set by Receiver Overruns */ #define IM_ALLOC_INT 0x08 /* Set when allocation request is completed */ #define IM_TX_EMPTY_INT 0x04 /* Set if the TX FIFO goes empty */ #define IM_TX_INT 0x02 /* Transmit Interrrupt */ #define IM_RCV_INT 0x01 /* Receive Interrupt */ /* Multicast Table Registers */ /* BANK 3 */ #define MCAST_REG1 0x0000 #define MCAST_REG2 0x0002 #define MCAST_REG3 0x0004 #define MCAST_REG4 0x0006 /* Management Interface Register (MII) */ /* BANK 3 */ #define MII_REG 0x0008 #define MII_MSK_CRS100 0x4000 /* Disables CRS100 detection during tx half dup */ #define MII_MDOE 0x0008 /* MII Output Enable */ #define MII_MCLK 0x0004 /* MII Clock, pin MDCLK */ #define MII_MDI 0x0002 /* MII Input, pin MDI */ #define MII_MDO 0x0001 /* MII Output, pin MDO */ /* Revision Register */ /* BANK 3 */ #define REV_REG 0x000A /* ( hi: chip id low: rev # ) */ /* Early RCV Register */ /* BANK 3 */ /* this is NOT on SMC9192 */ #define ERCV_REG 0x000C #define ERCV_RCV_DISCRD 0x0080 /* When 1 discards a packet being received */ #define ERCV_THRESHOLD 0x001F /* ERCV Threshold Mask */ /* External Register */ /* BANK 7 */ #define EXT_REG 0x0000 #define CHIP_9192 3 #define CHIP_9194 4 #define CHIP_9195 5 #define CHIP_9196 6 #define CHIP_91100 7 #define CHIP_91100FD 8 #define CHIP_91111FD 9 #if 0 static const char * chip_ids[ 15 ] = { NULL, NULL, NULL, /* 3 */ "SMC91C90/91C92", /* 4 */ "SMC91C94", /* 5 */ "SMC91C95", /* 6 */ "SMC91C96", /* 7 */ "SMC91C100", /* 8 */ "SMC91C100FD", /* 9 */ "SMC91C111", NULL, NULL, NULL, NULL, NULL}; #endif /* . Transmit status bits */ #define TS_SUCCESS 0x0001 #define TS_LOSTCAR 0x0400 #define TS_LATCOL 0x0200 #define TS_16COL 0x0010 /* . Receive status bits */ #define RS_ALGNERR 0x8000 #define RS_BRODCAST 0x4000 #define RS_BADCRC 0x2000 #define RS_ODDFRAME 0x1000 /* bug: the LAN91C111 never sets this on receive */ #define RS_TOOLONG 0x0800 #define RS_TOOSHORT 0x0400 #define RS_MULTICAST 0x0001 #define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) /* PHY Types */ enum { PHY_LAN83C183 = 1, /* LAN91C111 Internal PHY */ PHY_LAN83C180 }; /* PHY Register Addresses (LAN91C111 Internal PHY) */ /* PHY Control Register */ #define PHY_CNTL_REG 0x00 #define PHY_CNTL_RST 0x8000 /* 1=PHY Reset */ #define PHY_CNTL_LPBK 0x4000 /* 1=PHY Loopback */ #define PHY_CNTL_SPEED 0x2000 /* 1=100Mbps, 0=10Mpbs */ #define PHY_CNTL_ANEG_EN 0x1000 /* 1=Enable Auto negotiation */ #define PHY_CNTL_PDN 0x0800 /* 1=PHY Power Down mode */ #define PHY_CNTL_MII_DIS 0x0400 /* 1=MII 4 bit interface disabled */ #define PHY_CNTL_ANEG_RST 0x0200 /* 1=Reset Auto negotiate */ #define PHY_CNTL_DPLX 0x0100 /* 1=Full Duplex, 0=Half Duplex */ #define PHY_CNTL_COLTST 0x0080 /* 1= MII Colision Test */ /* PHY Status Register */ #define PHY_STAT_REG 0x01 #define PHY_STAT_CAP_T4 0x8000 /* 1=100Base-T4 capable */ #define PHY_STAT_CAP_TXF 0x4000 /* 1=100Base-X full duplex capable */ #define PHY_STAT_CAP_TXH 0x2000 /* 1=100Base-X half duplex capable */ #define PHY_STAT_CAP_TF 0x1000 /* 1=10Mbps full duplex capable */ #define PHY_STAT_CAP_TH 0x0800 /* 1=10Mbps half duplex capable */ #define PHY_STAT_CAP_SUPR 0x0040 /* 1=recv mgmt frames with not preamble */ #define PHY_STAT_ANEG_ACK 0x0020 /* 1=ANEG has completed */ #define PHY_STAT_REM_FLT 0x0010 /* 1=Remote Fault detected */ #define PHY_STAT_CAP_ANEG 0x0008 /* 1=Auto negotiate capable */ #define PHY_STAT_LINK 0x0004 /* 1=valid link */ #define PHY_STAT_JAB 0x0002 /* 1=10Mbps jabber condition */ #define PHY_STAT_EXREG 0x0001 /* 1=extended registers implemented */ /* PHY Identifier Registers */ #define PHY_ID1_REG 0x02 /* PHY Identifier 1 */ #define PHY_ID2_REG 0x03 /* PHY Identifier 2 */ /* PHY Auto-Negotiation Advertisement Register */ #define PHY_AD_REG 0x04 #define PHY_AD_NP 0x8000 /* 1=PHY requests exchange of Next Page */ #define PHY_AD_ACK 0x4000 /* 1=got link code word from remote */ #define PHY_AD_RF 0x2000 /* 1=advertise remote fault */ #define PHY_AD_T4 0x0200 /* 1=PHY is capable of 100Base-T4 */ #define PHY_AD_TX_FDX 0x0100 /* 1=PHY is capable of 100Base-TX FDPLX */ #define PHY_AD_TX_HDX 0x0080 /* 1=PHY is capable of 100Base-TX HDPLX */ #define PHY_AD_10_FDX 0x0040 /* 1=PHY is capable of 10Base-T FDPLX */ #define PHY_AD_10_HDX 0x0020 /* 1=PHY is capable of 10Base-T HDPLX */ #define PHY_AD_CSMA 0x0001 /* 1=PHY is capable of 802.3 CMSA */ /* PHY Auto-negotiation Remote End Capability Register */ #define PHY_RMT_REG 0x05 /* Uses same bit definitions as PHY_AD_REG */ /* PHY Configuration Register 1 */ #define PHY_CFG1_REG 0x10 #define PHY_CFG1_LNKDIS 0x8000 /* 1=Rx Link Detect Function disabled */ #define PHY_CFG1_XMTDIS 0x4000 /* 1=TP Transmitter Disabled */ #define PHY_CFG1_XMTPDN 0x2000 /* 1=TP Transmitter Powered Down */ #define PHY_CFG1_BYPSCR 0x0400 /* 1=Bypass scrambler/descrambler */ #define PHY_CFG1_UNSCDS 0x0200 /* 1=Unscramble Idle Reception Disable */ #define PHY_CFG1_EQLZR 0x0100 /* 1=Rx Equalizer Disabled */ #define PHY_CFG1_CABLE 0x0080 /* 1=STP(150ohm), 0=UTP(100ohm) */ #define PHY_CFG1_RLVL0 0x0040 /* 1=Rx Squelch level reduced by 4.5db */ #define PHY_CFG1_TLVL_SHIFT 2 /* Transmit Output Level Adjust */ #define PHY_CFG1_TLVL_MASK 0x003C #define PHY_CFG1_TRF_MASK 0x0003 /* Transmitter Rise/Fall time */ /* PHY Configuration Register 2 */ #define PHY_CFG2_REG 0x11 #define PHY_CFG2_APOLDIS 0x0020 /* 1=Auto Polarity Correction disabled */ #define PHY_CFG2_JABDIS 0x0010 /* 1=Jabber disabled */ #define PHY_CFG2_MREG 0x0008 /* 1=Multiple register access (MII mgt) */ #define PHY_CFG2_INTMDIO 0x0004 /* 1=Interrupt signaled with MDIO pulseo */ /* PHY Status Output (and Interrupt status) Register */ #define PHY_INT_REG 0x12 /* Status Output (Interrupt Status) */ #define PHY_INT_INT 0x8000 /* 1=bits have changed since last read */ #define PHY_INT_LNKFAIL 0x4000 /* 1=Link Not detected */ #define PHY_INT_LOSSSYNC 0x2000 /* 1=Descrambler has lost sync */ #define PHY_INT_CWRD 0x1000 /* 1=Invalid 4B5B code detected on rx */ #define PHY_INT_SSD 0x0800 /* 1=No Start Of Stream detected on rx */ #define PHY_INT_ESD 0x0400 /* 1=No End Of Stream detected on rx */ #define PHY_INT_RPOL 0x0200 /* 1=Reverse Polarity detected */ #define PHY_INT_JAB 0x0100 /* 1=Jabber detected */ #define PHY_INT_SPDDET 0x0080 /* 1=100Base-TX mode, 0=10Base-T mode */ #define PHY_INT_DPLXDET 0x0040 /* 1=Device in Full Duplex */ /* PHY Interrupt/Status Mask Register */ #define PHY_MASK_REG 0x13 /* Interrupt Mask */ /* Uses the same bit definitions as PHY_INT_REG */ /*------------------------------------------------------------------------- . I define some macros to make it easier to do somewhat common . or slightly complicated, repeated tasks. --------------------------------------------------------------------------*/ /* select a register bank, 0 to 3 */ #define SMC_SELECT_BANK(a,x) { SMC_outw((a), (x), BANK_SELECT ); } /* this enables an interrupt in the interrupt mask register */ #define SMC_ENABLE_INT(a,x) {\ unsigned char mask;\ SMC_SELECT_BANK((a),2);\ mask = SMC_inb((a), IM_REG );\ mask |= (x);\ SMC_outb( (a), mask, IM_REG ); \ } /* this disables an interrupt from the interrupt mask register */ #define SMC_DISABLE_INT(a,x) {\ unsigned char mask;\ SMC_SELECT_BANK(2);\ mask = SMC_inb( (a), IM_REG );\ mask &= ~(x);\ SMC_outb( (a), mask, IM_REG ); \ } /*---------------------------------------------------------------------- . Define the interrupts that I want to receive from the card . . I want: . IM_EPH_INT, for nasty errors . IM_RCV_INT, for happy received packets . IM_RX_OVRN_INT, because I have to kick the receiver . IM_MDINT, for PHY Register 18 Status Changes --------------------------------------------------------------------------*/ #define SMC_INTERRUPT_MASK (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | \ IM_MDINT) #endif /* _SMC_91111_H_ */ a id='n668' href='#n668'>668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718
require 'test/unit'

class TestArray < Test::Unit::TestCase
  def setup
    @verbose = $VERBOSE
    $VERBOSE = nil
    @cls = Array
  end

  def teardown
    $VERBOSE = @verbose
  end

  def test_0_literal
    assert_equal([1, 2, 3, 4], [1, 2] + [3, 4])
    assert_equal([1, 2, 1, 2], [1, 2] * 2)
    assert_equal("1:2", [1, 2] * ":")

    assert_equal([1, 2].hash, [1, 2].hash)

    assert_equal([2,3], [1,2,3] & [2,3,4])
    assert_equal([1,2,3,4], [1,2,3] | [2,3,4])
    assert_equal([1,2,3] - [2,3], [1])

    x = [0, 1, 2, 3, 4, 5]
    assert_equal(2, x[2])
    assert_equal([1, 2, 3], x[1..3])
    assert_equal([1, 2, 3], x[1,3])

    x[0, 2] = 10
    assert(x[0] == 10 && x[1] == 2)

    x[0, 0] = -1
    assert(x[0] == -1 && x[1] == 10)

    x[-1, 1] = 20
    assert(x[-1] == 20 && x.pop == 20)
  end

  def test_array_andor_0
    assert_equal([2], ([1,2,3]&[2,4,6]))
    assert_equal([1,2,3,4,6], ([1,2,3]|[2,4,6]))
  end

  def test_compact_0
    a = [nil, 1, nil, nil, 5, nil, nil]
    assert_equal [1, 5], a.compact
    assert_equal [nil, 1, nil, nil, 5, nil, nil], a
    a.compact!
    assert_equal [1, 5], a
  end

  def test_uniq_0
    x = [1, 1, 4, 2, 5, 4, 5, 1, 2]
    x.uniq!
    assert_equal([1, 4, 2, 5], x)
  end

  def test_empty_0
    assert_equal true, [].empty?
    assert_equal false, [1].empty?
    assert_equal false, [1, 1, 4, 2, 5, 4, 5, 1, 2].empty?
  end

  def test_sort_0
    x = ["it", "came", "to", "pass", "that", "..."]
    x = x.sort.join(" ")
    assert_equal("... came it pass that to", x)
    x = [2,5,3,1,7]
    x.sort!{|a,b| a<=>b}		# sort with condition
    assert_equal([1,2,3,5,7], x)
    x.sort!{|a,b| b-a}		# reverse sort
    assert_equal([7,5,3,2,1], x)
  end

  def test_split_0
    x = "The Book of Mormon"
    assert_equal(x.reverse, x.split(//).reverse!.join)
    assert_equal(x.reverse, x.reverse!)
    assert_equal("g:n:i:r:t:s: :e:t:y:b: :1", "1 byte string".split(//).reverse.join(":"))
    x = "a b c  d"
    assert_equal(['a', 'b', 'c', 'd'], x.split)
    assert_equal(['a', 'b', 'c', 'd'], x.split(' '))
  end

  def test_misc_0
    assert(defined? "a".chomp)
    assert_equal(["a", "b", "c"], "abc".scan(/./))
    assert_equal([["1a"], ["2b"], ["3c"]], "1a2b3c".scan(/(\d.)/))
    # non-greedy match
    assert_equal([["a", "12"], ["b", "22"]], "a=12;b=22".scan(/(.*?)=(\d*);?/))

    x = [1]
    assert_equal('1:1:1:1:1', (x * 5).join(":"))
    assert_equal('1', (x * 1).join(":"))
    assert_equal('', (x * 0).join(":"))

    *x = *(1..7).to_a
    assert_equal(7, x.size)
    assert_equal([1, 2, 3, 4, 5, 6, 7], x)

    x = [1,2,3]
    x[1,0] = x
    assert_equal([1,1,2,3,2,3], x)

    x = [1,2,3]
    x[-1,0] = x
    assert_equal([1,2,1,2,3,3], x)

    x = [1,2,3]
    x.concat(x)
    assert_equal([1,2,3,1,2,3], x)

    x = [1,2,3]
    x.clear
    assert_equal([], x)

    x = [1,2,3]
    y = x.dup
    x << 4
    y << 5
    assert_equal([1,2,3,4], x)
    assert_equal([1,2,3,5], y)
  end

  def test_beg_end_0
    x = [1, 2, 3, 4, 5]

    assert_equal(1, x.first)
    assert_equal([1], x.first(1))
    assert_equal([1, 2, 3], x.first(3))

    assert_equal(5, x.last)
    assert_equal([5], x.last(1))
    assert_equal([3, 4, 5], x.last(3))

    assert_equal(1, x.shift)
    assert_equal([2, 3, 4], x.shift(3))
    assert_equal([5], x)

    assert_equal([2, 3, 4, 5], x.unshift(2, 3, 4))
    assert_equal([1, 2, 3, 4, 5], x.unshift(1))
    assert_equal([1, 2, 3, 4, 5], x)

    assert_equal(5, x.pop)
    assert_equal([3, 4], x.pop(2))
    assert_equal([1, 2], x)

    assert_equal([1, 2, 3, 4], x.push(3, 4))
    assert_equal([1, 2, 3, 4, 5], x.push(5))
    assert_equal([1, 2, 3, 4, 5], x)
  end

  def test_find_all_0
    assert_respond_to([], :find_all)
    assert_respond_to([], :select)       # Alias
    assert_equal([], [].find_all{ |obj| obj == "foo"})

    x = ["foo", "bar", "baz", "baz", 1, 2, 3, 3, 4]
    assert_equal(["baz","baz"], x.find_all{ |obj| obj == "baz" })
    assert_equal([3,3], x.find_all{ |obj| obj == 3 })
  end

  def test_fill_0
    assert_equal([-1, -1, -1, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1))
    assert_equal([0, 1, 2, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, 3))
    assert_equal([0, 1, 2, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3, 2))
    assert_equal([0, 1, 2, -1, -1, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, 3, 5))
    assert_equal([0, 1, -1, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2, 2))
    assert_equal([0, 1, -1, -1, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, 2, 5))
    assert_equal([0, 1, 2, 3, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, -2, 1))
    assert_equal([0, 1, 2, 3, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, -2, 3))
    assert_equal([0, 1, 2, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3..4))
    assert_equal([0, 1, 2, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3...4))
    assert_equal([0, 1, -1, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2..-2))
    assert_equal([0, 1, -1, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2...-2))
    assert_equal([10, 11, 12, 13, 14, 15], [0, 1, 2, 3, 4, 5].fill{|i| i+10})
    assert_equal([0, 1, 2, 13, 14, 15], [0, 1, 2, 3, 4, 5].fill(3){|i| i+10})
    assert_equal([0, 1, 2, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(3, 2){|i| i+10})
    assert_equal([0, 1, 2, 13, 14, 15, 16, 17], [0, 1, 2, 3, 4, 5].fill(3, 5){|i| i+10})
    assert_equal([0, 1, 2, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(3..4){|i| i+10})
    assert_equal([0, 1, 2, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(3...4){|i| i+10})
    assert_equal([0, 1, 12, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(2..-2){|i| i+10})
    assert_equal([0, 1, 12, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(2...-2){|i| i+10})
  end

  # From rubicon

  def test_00_new
    a = @cls.new()
    assert_instance_of(@cls, a)
    assert_equal(0, a.length)
    assert_nil(a[0])
  end

  def test_01_square_brackets
    a = @cls[ 5, 4, 3, 2, 1 ]
    assert_instance_of(@cls, a)
    assert_equal(5, a.length)
    5.times { |i| assert_equal(5-i, a[i]) }
    assert_nil(a[6])
  end

  def test_AND # '&'
    assert_equal(@cls[1, 3], @cls[ 1, 1, 3, 5 ] & @cls[ 1, 2, 3 ])
    assert_equal(@cls[],     @cls[ 1, 1, 3, 5 ] & @cls[ ])
    assert_equal(@cls[],     @cls[  ]           & @cls[ 1, 2, 3 ])
    assert_equal(@cls[],     @cls[ 1, 2, 3 ]    & @cls[ 4, 5, 6 ])
  end

  def test_MUL # '*'
    assert_equal(@cls[], @cls[]*3)
    assert_equal(@cls[1, 1, 1], @cls[1]*3)
    assert_equal(@cls[1, 2, 1, 2, 1, 2], @cls[1, 2]*3)
    assert_equal(@cls[], @cls[1, 2, 3] * 0)
    assert_raise(ArgumentError) { @cls[1, 2]*(-3) }

    assert_equal('1-2-3-4-5', @cls[1, 2, 3, 4, 5] * '-')
    assert_equal('12345',     @cls[1, 2, 3, 4, 5] * '')

  end

  def test_PLUS # '+'
    assert_equal(@cls[],     @cls[]  + @cls[])
    assert_equal(@cls[1],    @cls[1] + @cls[])
    assert_equal(@cls[1],    @cls[]  + @cls[1])
    assert_equal(@cls[1, 1], @cls[1] + @cls[1])
    assert_equal(@cls['cat', 'dog', 1, 2, 3], %w(cat dog) + (1..3).to_a)
  end

  def test_MINUS # '-'
    assert_equal(@cls[],  @cls[1] - @cls[1])
    assert_equal(@cls[1], @cls[1, 2, 3, 4, 5] - @cls[2, 3, 4, 5])
    # Ruby 1.8 feature change
    #assert_equal(@cls[1], @cls[1, 2, 1, 3, 1, 4, 1, 5] - @cls[2, 3, 4, 5])
    assert_equal(@cls[1, 1, 1, 1], @cls[1, 2, 1, 3, 1, 4, 1, 5] - @cls[2, 3, 4, 5])
    a = @cls[]
    1000.times { a << 1 }
    assert_equal(1000, a.length)
    #assert_equal(@cls[1], a - @cls[2])
    assert_equal(@cls[1] * 1000, a - @cls[2])
    #assert_equal(@cls[1],  @cls[1, 2, 1] - @cls[2])
    assert_equal(@cls[1, 1],  @cls[1, 2, 1] - @cls[2])
    assert_equal(@cls[1, 2, 3], @cls[1, 2, 3] - @cls[4, 5, 6])
  end

  def test_LSHIFT # '<<'
    a = @cls[]
    a << 1
    assert_equal(@cls[1], a)
    a << 2 << 3
    assert_equal(@cls[1, 2, 3], a)
    a << nil << 'cat'
    assert_equal(@cls[1, 2, 3, nil, 'cat'], a)
    a << a
    assert_equal(@cls[1, 2, 3, nil, 'cat', a], a)
  end

  def test_CMP # '<=>'
    assert_equal(0,  @cls[] <=> @cls[])
    assert_equal(0,  @cls[1] <=> @cls[1])
    assert_equal(0,  @cls[1, 2, 3, 'cat'] <=> @cls[1, 2, 3, 'cat'])
    assert_equal(-1, @cls[] <=> @cls[1])
    assert_equal(1,  @cls[1] <=> @cls[])
    assert_equal(-1, @cls[1, 2, 3] <=> @cls[1, 2, 3, 'cat'])
    assert_equal(1,  @cls[1, 2, 3, 'cat'] <=> @cls[1, 2, 3])
    assert_equal(-1, @cls[1, 2, 3, 'cat'] <=> @cls[1, 2, 3, 'dog'])
    assert_equal(1,  @cls[1, 2, 3, 'dog'] <=> @cls[1, 2, 3, 'cat'])
  end

  def test_EQUAL # '=='
    assert(@cls[] == @cls[])
    assert(@cls[1] == @cls[1])
    assert(@cls[1, 1, 2, 2] == @cls[1, 1, 2, 2])
    assert(@cls[1.0, 1.0, 2.0, 2.0] == @cls[1, 1, 2, 2])
  end

  def test_VERY_EQUAL # '==='
    assert(@cls[] === @cls[])
    assert(@cls[1] === @cls[1])
    assert(@cls[1, 1, 2, 2] === @cls[1, 1, 2, 2])
    assert(@cls[1.0, 1.0, 2.0, 2.0] === @cls[1, 1, 2, 2])
  end

  def test_AREF # '[]'
    a = @cls[*(1..100).to_a]

    assert_equal(1, a[0])
    assert_equal(100, a[99])
    assert_nil(a[100])
    assert_equal(100, a[-1])
    assert_equal(99,  a[-2])
    assert_equal(1,   a[-100])
    assert_nil(a[-101])
    assert_nil(a[-101,0])
    assert_nil(a[-101,1])
    assert_nil(a[-101,-1])
    assert_nil(a[10,-1])

    assert_equal(@cls[1],   a[0,1])
    assert_equal(@cls[100], a[99,1])
    assert_equal(@cls[],    a[100,1])
    assert_equal(@cls[100], a[99,100])
    assert_equal(@cls[100], a[-1,1])
    assert_equal(@cls[99],  a[-2,1])
    assert_equal(@cls[],    a[-100,0])
    assert_equal(@cls[1],   a[-100,1])

    assert_equal(@cls[10, 11, 12], a[9, 3])
    assert_equal(@cls[10, 11, 12], a[-91, 3])

    assert_equal(@cls[1],   a[0..0])
    assert_equal(@cls[100], a[99..99])
    assert_equal(@cls[],    a[100..100])
    assert_equal(@cls[100], a[99..200])
    assert_equal(@cls[100], a[-1..-1])
    assert_equal(@cls[99],  a[-2..-2])

    assert_equal(@cls[10, 11, 12], a[9..11])
    assert_equal(@cls[10, 11, 12], a[-91..-89])

    assert_nil(a[10, -3])
    # Ruby 1.8 feature change:
    # Array#[size..x] returns [] instead of nil.
    #assert_nil(a[10..7])
    assert_equal [], a[10..7]

    assert_raise(TypeError) {a['cat']}
  end

  def test_ASET # '[]='
    a = @cls[*(0..99).to_a]
    assert_equal(0, a[0] = 0)
    assert_equal(@cls[0] + @cls[*(1..99).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(0, a[10,10] = 0)
    assert_equal(@cls[*(0..9).to_a] + @cls[0] + @cls[*(20..99).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(0, a[-1] = 0)
    assert_equal(@cls[*(0..98).to_a] + @cls[0], a)

    a = @cls[*(0..99).to_a]
    assert_equal(0, a[-10, 10] = 0)
    assert_equal(@cls[*(0..89).to_a] + @cls[0], a)

    a = @cls[*(0..99).to_a]
    assert_equal(0, a[0,1000] = 0)
    assert_equal(@cls[0] , a)

    a = @cls[*(0..99).to_a]
    assert_equal(0, a[10..19] = 0)
    assert_equal(@cls[*(0..9).to_a] + @cls[0] + @cls[*(20..99).to_a], a)

    b = @cls[*%w( a b c )]
    a = @cls[*(0..99).to_a]
    assert_equal(b, a[0,1] = b)
    assert_equal(b + @cls[*(1..99).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(b, a[10,10] = b)
    assert_equal(@cls[*(0..9).to_a] + b + @cls[*(20..99).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(b, a[-1, 1] = b)
    assert_equal(@cls[*(0..98).to_a] + b, a)

    a = @cls[*(0..99).to_a]
    assert_equal(b, a[-10, 10] = b)
    assert_equal(@cls[*(0..89).to_a] + b, a)

    a = @cls[*(0..99).to_a]
    assert_equal(b, a[0,1000] = b)
    assert_equal(b , a)

    a = @cls[*(0..99).to_a]
    assert_equal(b, a[10..19] = b)
    assert_equal(@cls[*(0..9).to_a] + b + @cls[*(20..99).to_a], a)

    # Ruby 1.8 feature change:
    # assigning nil does not remove elements.
=begin
    a = @cls[*(0..99).to_a]
    assert_equal(nil, a[0,1] = nil)
    assert_equal(@cls[*(1..99).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(nil, a[10,10] = nil)
    assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(nil, a[-1, 1] = nil)
    assert_equal(@cls[*(0..98).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(nil, a[-10, 10] = nil)
    assert_equal(@cls[*(0..89).to_a], a)

    a = @cls[*(0..99).to_a]
    assert_equal(nil, a[0,1000] = nil)
    assert_equal(@cls[] , a)

    a = @cls[*(0..99).to_a]
    assert_equal(nil, a[10..19] = nil)
    assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a)
=end

    a = @cls[1, 2, 3]
    a[1, 0] = a
    assert_equal([1, 1, 2, 3, 2, 3], a)

    a = @cls[1, 2, 3]
    a[-1, 0] = a
    assert_equal([1, 2, 1, 2, 3, 3], a)
  end

  def test_assoc
    a1 = @cls[*%w( cat feline )]
    a2 = @cls[*%w( dog canine )]
    a3 = @cls[*%w( mule asinine )]

    a = @cls[ a1, a2, a3 ]

    assert_equal(a1, a.assoc('cat'))
    assert_equal(a3, a.assoc('mule'))
    assert_equal(nil, a.assoc('asinine'))
    assert_equal(nil, a.assoc('wombat'))
    assert_equal(nil, a.assoc(1..2))
  end

  def test_at
    a = @cls[*(0..99).to_a]
    assert_equal(0,   a.at(0))
    assert_equal(10,  a.at(10))
    assert_equal(99,  a.at(99))
    assert_equal(nil, a.at(100))
    assert_equal(99,  a.at(-1))
    assert_equal(0,  a.at(-100))
    assert_equal(nil, a.at(-101))
    assert_raise(TypeError) { a.at('cat') }
  end

  def test_clear
    a = @cls[1, 2, 3]
    b = a.clear
    assert_equal(@cls[], a)
    assert_equal(@cls[], b)
    assert_equal(a.__id__, b.__id__)
  end

  def test_clone
    for taint in [ false, true ]
      for untrust in [ false, true ]
        for frozen in [ false, true ]
          a = @cls[*(0..99).to_a]
          a.taint  if taint
          a.untrust  if untrust
          a.freeze if frozen
          b = a.clone

          assert_equal(a, b)
          assert(a.__id__ != b.__id__)
          assert_equal(a.frozen?, b.frozen?)
          assert_equal(a.untrusted?, b.untrusted?)
          assert_equal(a.tainted?, b.tainted?)
        end
      end
    end
  end

  def test_collect
    a = @cls[ 1, 'cat', 1..1 ]
    assert_equal([ Fixnum, String, Range], a.collect {|e| e.class} )
    assert_equal([ 99, 99, 99], a.collect { 99 } )

    assert_equal([], @cls[].collect { 99 })

    # Ruby 1.9 feature change:
    # Enumerable#collect without block returns an Enumerator.
    #assert_equal([1, 2, 3], @cls[1, 2, 3].collect)
    assert_kind_of Enumerator, @cls[1, 2, 3].collect
  end

  # also update map!
  def test_collect!
    a = @cls[ 1, 'cat', 1..1 ]
    assert_equal([ Fixnum, String, Range], a.collect! {|e| e.class} )
    assert_equal([ Fixnum, String, Range], a)

    a = @cls[ 1, 'cat', 1..1 ]
    assert_equal([ 99, 99, 99], a.collect! { 99 } )
    assert_equal([ 99, 99, 99], a)

    a = @cls[ ]
    assert_equal([], a.collect! { 99 })
    assert_equal([], a)
  end

  def test_compact
    a = @cls[ 1, nil, nil, 2, 3, nil, 4 ]
    assert_equal(@cls[1, 2, 3, 4], a.compact)

    a = @cls[ nil, 1, nil, 2, 3, nil, 4 ]
    assert_equal(@cls[1, 2, 3, 4], a.compact)

    a = @cls[ 1, nil, nil, 2, 3, nil, 4, nil ]
    assert_equal(@cls[1, 2, 3, 4], a.compact)

    a = @cls[ 1, 2, 3, 4 ]
    assert_equal(@cls[1, 2, 3, 4], a.compact)
  end

  def test_compact!
    a = @cls[ 1, nil, nil, 2, 3, nil, 4 ]
    assert_equal(@cls[1, 2, 3, 4], a.compact!)
    assert_equal(@cls[1, 2, 3, 4], a)

    a = @cls[ nil, 1, nil, 2, 3, nil, 4 ]
    assert_equal(@cls[1, 2, 3, 4], a.compact!)
    assert_equal(@cls[1, 2, 3, 4], a)

    a = @cls[ 1, nil, nil, 2, 3, nil, 4, nil ]
    assert_equal(@cls[1, 2, 3, 4], a.compact!)
    assert_equal(@cls[1, 2, 3, 4], a)

    a = @cls[ 1, 2, 3, 4 ]
    assert_equal(nil, a.compact!)
    assert_equal(@cls[1, 2, 3, 4], a)
  end

  def test_concat
    assert_equal(@cls[1, 2, 3, 4],     @cls[1, 2].concat(@cls[3, 4]))
    assert_equal(@cls[1, 2, 3, 4],     @cls[].concat(@cls[1, 2, 3, 4]))
    assert_equal(@cls[1, 2, 3, 4],     @cls[1, 2, 3, 4].concat(@cls[]))
    assert_equal(@cls[],               @cls[].concat(@cls[]))
    assert_equal(@cls[@cls[1, 2], @cls[3, 4]], @cls[@cls[1, 2]].concat(@cls[@cls[3, 4]]))

    a = @cls[1, 2, 3]
    a.concat(a)
    assert_equal([1, 2, 3, 1, 2, 3], a)
  end

  def test_count
    a = @cls[1, 2, 3, 1, 2]
    assert_equal(5, a.count)
    assert_equal(2, a.count(1))
    assert_equal(3, a.count {|x| x % 2 == 1 })
    assert_equal(2, a.count(1) {|x| x % 2 == 1 })
    assert_raise(ArgumentError) { a.count(0, 1) }
  end

  def test_delete
    a = @cls[*('cab'..'cat').to_a]
    assert_equal('cap', a.delete('cap'))
    assert_equal(@cls[*('cab'..'cao').to_a] + @cls[*('caq'..'cat').to_a], a)

    a = @cls[*('cab'..'cat').to_a]
    assert_equal('cab', a.delete('cab'))
    assert_equal(@cls[*('cac'..'cat').to_a], a)

    a = @cls[*('cab'..'cat').to_a]
    assert_equal('cat', a.delete('cat'))
    assert_equal(@cls[*('cab'..'cas').to_a], a)

    a = @cls[*('cab'..'cat').to_a]
    assert_equal(nil, a.delete('cup'))
    assert_equal(@cls[*('cab'..'cat').to_a], a)

    a = @cls[*('cab'..'cat').to_a]
    assert_equal(99, a.delete('cup') { 99 } )
    assert_equal(@cls[*('cab'..'cat').to_a], a)
  end

  def test_delete_at
    a = @cls[*(1..5).to_a]
    assert_equal(3, a.delete_at(2))
    assert_equal(@cls[1, 2, 4, 5], a)

    a = @cls[*(1..5).to_a]
    assert_equal(4, a.delete_at(-2))
    assert_equal(@cls[1, 2, 3, 5], a)

    a = @cls[*(1..5).to_a]
    assert_equal(nil, a.delete_at(5))
    assert_equal(@cls[1, 2, 3, 4, 5], a)

    a = @cls[*(1..5).to_a]
    assert_equal(nil, a.delete_at(-6))
    assert_equal(@cls[1, 2, 3, 4, 5], a)
  end

  # also reject!
  def test_delete_if
    a = @cls[ 1, 2, 3, 4, 5 ]
    assert_equal(a, a.delete_if { false })
    assert_equal(@cls[1, 2, 3, 4, 5], a)

    a = @cls[ 1, 2, 3, 4, 5 ]
    assert_equal(a, a.delete_if { true })
    assert_equal(@cls[], a)

    a = @cls[ 1, 2, 3, 4, 5 ]
    assert_equal(a, a.delete_if { |i| i > 3 })
    assert_equal(@cls[1, 2, 3], a)
  end

  def test_dup
    for taint in [ false, true ]
      for frozen in [ false, true ]
        a = @cls[*(0..99).to_a]
        a.taint  if taint
        a.freeze if frozen
        b = a.dup

        assert_equal(a, b)
        assert(a.__id__ != b.__id__)
        assert_equal(false, b.frozen?)
        assert_equal(a.tainted?, b.tainted?)
      end
    end
  end

  def test_each
    a = @cls[*%w( ant bat cat dog )]
    i = 0
    a.each { |e|
      assert_equal(a[i], e)
      i += 1
    }
    assert_equal(4, i)

    a = @cls[]
    i = 0
    a.each { |e|
      assert_equal(a[i], e)
      i += 1
    }
    assert_equal(0, i)

    assert_equal(a, a.each {})
  end

  def test_each_index
    a = @cls[*%w( ant bat cat dog )]
    i = 0
    a.each_index { |ind|
      assert_equal(i, ind)
      i += 1
    }
    assert_equal(4, i)

    a = @cls[]
    i = 0
    a.each_index { |ind|
      assert_equal(i, ind)
      i += 1
    }
    assert_equal(0, i)

    assert_equal(a, a.each_index {})
  end

  def test_empty?
    assert(@cls[].empty?)
    assert(!@cls[1].empty?)
  end

  def test_eql?
    assert(@cls[].eql?(@cls[]))
    assert(@cls[1].eql?(@cls[1]))
    assert(@cls[1, 1, 2, 2].eql?(@cls[1, 1, 2, 2]))
    assert(!@cls[1.0, 1.0, 2.0, 2.0].eql?(@cls[1, 1, 2, 2]))
  end

  def test_fill
    assert_equal(@cls[],   @cls[].fill(99))
    assert_equal(@cls[],   @cls[].fill(99, 0))
    assert_equal(@cls[99], @cls[].fill(99, 0, 1))
    assert_equal(@cls[99], @cls[].fill(99, 0..0))

    assert_equal(@cls[99],   @cls[1].fill(99))
    assert_equal(@cls[99],   @cls[1].fill(99, 0))
    assert_equal(@cls[99],   @cls[1].fill(99, 0, 1))
    assert_equal(@cls[99],   @cls[1].fill(99, 0..0))

    assert_equal(@cls[99, 99], @cls[1, 2].fill(99))
    assert_equal(@cls[99, 99], @cls[1, 2].fill(99, 0))
    assert_equal(@cls[99, 99], @cls[1, 2].fill(99, nil))
    assert_equal(@cls[1,  99], @cls[1, 2].fill(99, 1, nil))
    assert_equal(@cls[99,  2], @cls[1, 2].fill(99, 0, 1))
    assert_equal(@cls[99,  2], @cls[1, 2].fill(99, 0..0))
  end

  def test_first
    assert_equal(3,   @cls[3, 4, 5].first)
    assert_equal(nil, @cls[].first)
  end

  def test_flatten
    a1 = @cls[ 1, 2, 3]
    a2 = @cls[ 5, 6 ]
    a3 = @cls[ 4, a2 ]
    a4 = @cls[ a1, a3 ]
    assert_equal(@cls[1, 2, 3, 4, 5, 6], a4.flatten)
    assert_equal(@cls[ a1, a3], a4)

    a5 = @cls[ a1, @cls[], a3 ]
    assert_equal(@cls[1, 2, 3, 4, 5, 6], a5.flatten)
    assert_equal(@cls[], @cls[].flatten)
    assert_equal(@cls[],
                 @cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten)

    assert_raise(TypeError, "[ruby-dev:31197]") { [[]].flatten("") }

    a6 = @cls[[1, 2], 3]
    a6.taint
    a6.untrust
    a7 = a6.flatten
    assert_equal(true, a7.tainted?)
    assert_equal(true, a7.untrusted?)

    a8 = @cls[[1, 2], 3]
    a9 = a8.flatten(0)
    assert_equal(a8, a9)
    assert_not_same(a8, a9)
  end

  def test_flatten!
    a1 = @cls[ 1, 2, 3]
    a2 = @cls[ 5, 6 ]
    a3 = @cls[ 4, a2 ]
    a4 = @cls[ a1, a3 ]
    assert_equal(@cls[1, 2, 3, 4, 5, 6], a4.flatten!)
    assert_equal(@cls[1, 2, 3, 4, 5, 6], a4)

    a5 = @cls[ a1, @cls[], a3 ]
    assert_equal(@cls[1, 2, 3, 4, 5, 6], a5.flatten!)
    assert_nil(a5.flatten!(0), '[ruby-core:23382]')
    assert_equal(@cls[1, 2, 3, 4, 5, 6], a5)

    assert_equal(@cls[], @cls[].flatten)
    assert_equal(@cls[],
                 @cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten)

    assert_nil(@cls[].flatten!(0), '[ruby-core:23382]')
  end

  def test_flatten_with_callcc
    respond_to?(:callcc, true) or require 'continuation'
    o = Object.new
    def o.to_ary() callcc {|k| @cont = k; [1,2,3]} end
    begin
      assert_equal([10, 20, 1, 2, 3, 30, 1, 2, 3, 40], [10, 20, o, 30, o, 40].flatten)
    rescue => e
    else
      o.instance_eval {@cont}.call
    end
    assert_instance_of(RuntimeError, e, '[ruby-dev:34798]')
    assert_match(/reentered/, e.message, '[ruby-dev:34798]')
  end

  def test_hash
    a1 = @cls[ 'cat', 'dog' ]
    a2 = @cls[ 'cat', 'dog' ]
    a3 = @cls[ 'dog', 'cat' ]
    assert(a1.hash == a2.hash)
    assert(a1.hash != a3.hash)
  end

  def test_include?
    a = @cls[ 'cat', 99, /a/, @cls[ 1, 2, 3] ]
    assert(a.include?('cat'))
    assert(a.include?(99))
    assert(a.include?(/a/))
    assert(a.include?([1,2,3]))
    assert(!a.include?('ca'))
    assert(!a.include?([1,2]))
  end

  def test_index
    a = @cls[ 'cat', 99, /a/, 99, @cls[ 1, 2, 3] ]
    assert_equal(0, a.index('cat'))
    assert_equal(1, a.index(99))
    assert_equal(4, a.index([1,2,3]))
    assert_nil(a.index('ca'))
    assert_nil(a.index([1,2]))

    assert_equal(1, a.index(99) {|x| x == 'cat' })
  end

  def test_values_at
    a = @cls[*('a'..'j').to_a]
    assert_equal(@cls['a', 'c', 'e'], a.values_at(0, 2, 4))
    assert_equal(@cls['j', 'h', 'f'], a.values_at(-1, -3, -5))
    assert_equal(@cls['h', nil, 'a'], a.values_at(-3, 99, 0))
  end

  def test_join
    $, = ""
    a = @cls[]
    assert_equal("", a.join)
    assert_equal("", a.join(','))

    $, = ""
    a = @cls[1, 2]
    assert_equal("12", a.join)
    assert_equal("1,2", a.join(','))

    $, = ""
    a = @cls[1, 2, 3]
    assert_equal("123", a.join)
    assert_equal("1,2,3", a.join(','))

    $, = ":"
    a = @cls[1, 2, 3]
    assert_equal("1:2:3", a.join)
    assert_equal("1,2,3", a.join(','))

    $, = ""
    a = @cls[1, 2, 3]
    a.taint
    a.untrust
    s = a.join
    assert_equal(true, s.tainted?)
    assert_equal(true, s.untrusted?)
  ensure
    $, = nil
  end

  def test_last
    assert_equal(nil, @cls[].last)
    assert_equal(1, @cls[1].last)
    assert_equal(99, @cls[*(3..99).to_a].last)
  end

  def test_length
    assert_equal(0, @cls[].length)
    assert_equal(1, @cls[1].length)
    assert_equal(2, @cls[1, nil].length)
    assert_equal(2, @cls[nil, 1].length)
    assert_equal(234, @cls[*(0..233).to_a].length)
  end

  # also update collect!
  def test_map!
    a = @cls[ 1, 'cat', 1..1 ]
    assert_equal(@cls[ Fixnum, String, Range], a.map! {|e| e.class} )
    assert_equal(@cls[ Fixnum, String, Range], a)

    a = @cls[ 1, 'cat', 1..1 ]
    assert_equal(@cls[ 99, 99, 99], a.map! { 99 } )
    assert_equal(@cls[ 99, 99, 99], a)

    a = @cls[ ]
    assert_equal(@cls[], a.map! { 99 })
    assert_equal(@cls[], a)
  end

  def test_pack
    a = @cls[*%w( cat wombat x yy)]
    assert_equal("catwomx  yy ", a.pack("A3A3A3A3"))
    assert_equal("cat", a.pack("A*"))
    assert_equal("cwx  yy ", a.pack("A3@1A3@2A3A3"))
    assert_equal("catwomx\000\000yy\000", a.pack("a3a3a3a3"))
    assert_equal("cat", a.pack("a*"))
    assert_equal("ca", a.pack("a2"))
    assert_equal("cat\000\000", a.pack("a5"))

    assert_equal("\x61",     @cls["01100001"].pack("B8"))
    assert_equal("\x61",     @cls["01100001"].pack("B*"))
    assert_equal("\x61",     @cls["0110000100110111"].pack("B8"))
    assert_equal("\x61\x37", @cls["0110000100110111"].pack("B16"))
    assert_equal("\x61\x37", @cls["01100001", "00110111"].pack("B8B8"))
    assert_equal("\x60",     @cls["01100001"].pack("B4"))
    assert_equal("\x40",     @cls["01100001"].pack("B2"))

    assert_equal("\x86",     @cls["01100001"].pack("b8"))
    assert_equal("\x86",     @cls["01100001"].pack("b*"))
    assert_equal("\x86",     @cls["0110000100110111"].pack("b8"))
    assert_equal("\x86\xec", @cls["0110000100110111"].pack("b16"))
    assert_equal("\x86\xec", @cls["01100001", "00110111"].pack("b8b8"))
    assert_equal("\x06",     @cls["01100001"].pack("b4"))
    assert_equal("\x02",     @cls["01100001"].pack("b2"))

    assert_equal("ABC",      @cls[ 65, 66, 67 ].pack("C3"))
    assert_equal("\377BC",   @cls[ -1, 66, 67 ].pack("C*"))
    assert_equal("ABC",      @cls[ 65, 66, 67 ].pack("c3"))
    assert_equal("\377BC",   @cls[ -1, 66, 67 ].pack("c*"))


    assert_equal("AB\n\x10",  @cls["4142", "0a", "12"].pack("H4H2H1"))
    assert_equal("AB\n\x02",  @cls["1424", "a0", "21"].pack("h4h2h1"))

    assert_equal("abc=02def=\ncat=\n=01=\n",
                 @cls["abc\002def", "cat", "\001"].pack("M9M3M4"))

    assert_equal("aGVsbG8K\n",  @cls["hello\n"].pack("m"))
    assert_equal(",:&5L;&\\*:&5L;&\\*\n",  @cls["hello\nhello\n"].pack("u"))

    assert_equal("\u{a9 42 2260}", @cls[0xa9, 0x42, 0x2260].pack("U*"))


    format = "c2x5CCxsdils_l_a6";
    # Need the expression in here to force ary[5] to be numeric.  This avoids
    # test2 failing because ary2 goes str->numeric->str and ary does not.
    ary = [1, -100, 127, 128, 32767, 987.654321098/100.0,
      12345, 123456, -32767, -123456, "abcdef"]
    x    = ary.pack(format)
    ary2 = x.unpack(format)

    assert_equal(ary.length, ary2.length)
    assert_equal(ary.join(':'), ary2.join(':'))
    assert_not_nil(x =~ /def/)

=begin
    skipping "Not tested:
        D,d & double-precision float, native format\\
        E & double-precision float, little-endian byte order\\
        e & single-precision float, little-endian byte order\\
        F,f & single-precision float, native format\\
        G & double-precision float, network (big-endian) byte order\\
        g & single-precision float, network (big-endian) byte order\\
        I & unsigned integer\\
        i & integer\\
        L & unsigned long\\
        l & long\\

        N & long, network (big-endian) byte order\\
        n & short, network (big-endian) byte-order\\
        P & pointer to a structure (fixed-length string)\\
        p & pointer to a null-terminated string\\
        S & unsigned short\\
        s & short\\
        V & long, little-endian byte order\\
        v & short, little-endian byte order\\
        X & back up a byte\\
        x & null byte\\
        Z & ASCII string (null padded, count is width)\\
"
=end
  end

  def test_pop
    a = @cls[ 'cat', 'dog' ]
    assert_equal('dog', a.pop)
    assert_equal(@cls['cat'], a)
    assert_equal('cat', a.pop)
    assert_equal(@cls[], a)
    assert_nil(a.pop)
    assert_equal(@cls[], a)
  end

  def test_push
    a = @cls[1, 2, 3]
    assert_equal(@cls[1, 2, 3, 4, 5], a.push(4, 5))
    assert_equal(@cls[1, 2, 3, 4, 5, nil], a.push(nil))
    # Ruby 1.8 feature:
    # Array#push accepts any number of arguments.
    #assert_raise(ArgumentError, "a.push()") { a.push() }
    a.push
    assert_equal @cls[1, 2, 3, 4, 5, nil], a
    a.push 6, 7
    assert_equal @cls[1, 2, 3, 4, 5, nil, 6, 7], a
  end

  def test_rassoc
    a1 = @cls[*%w( cat  feline )]
    a2 = @cls[*%w( dog  canine )]
    a3 = @cls[*%w( mule asinine )]
    a  = @cls[ a1, a2, a3 ]

    assert_equal(a1,  a.rassoc('feline'))
    assert_equal(a3,  a.rassoc('asinine'))
    assert_equal(nil, a.rassoc('dog'))
    assert_equal(nil, a.rassoc('mule'))
    assert_equal(nil, a.rassoc(1..2))
  end

  # also delete_if
  def test_reject!
    a = @cls[ 1, 2, 3, 4, 5 ]
    assert_equal(nil, a.reject! { false })
    assert_equal(@cls[1, 2, 3, 4, 5], a)

    a = @cls[ 1, 2, 3, 4, 5 ]
    assert_equal(a, a.reject! { true })
    assert_equal(@cls[], a)

    a = @cls[ 1, 2, 3, 4, 5 ]
    assert_equal(a, a.reject! { |i| i > 3 })
    assert_equal(@cls[1, 2, 3], a)
  end

  def test_replace
    a = @cls[ 1, 2, 3]
    a_id = a.__id__
    assert_equal(@cls[4, 5, 6], a.replace(@cls[4, 5, 6]))
    assert_equal(@cls[4, 5, 6], a)
    assert_equal(a_id, a.__id__)
    assert_equal(@cls[], a.replace(@cls[]))
  end

  def test_reverse
    a = @cls[*%w( dog cat bee ant )]
    assert_equal(@cls[*%w(ant bee cat dog)], a.reverse)
    assert_equal(@cls[*%w(dog cat bee ant)], a)
    assert_equal(@cls[], @cls[].reverse)
  end

  def test_reverse!
    a = @cls[*%w( dog cat bee ant )]
    assert_equal(@cls[*%w(ant bee cat dog)], a.reverse!)
    assert_equal(@cls[*%w(ant bee cat dog)], a)
    # Ruby 1.8 feature change:
    # Array#reverse always returns self.
    #assert_nil(@cls[].reverse!)
    assert_equal @cls[], @cls[].reverse!
  end

  def test_reverse_each
    a = @cls[*%w( dog cat bee ant )]
    i = a.length
    a.reverse_each { |e|
      i -= 1
      assert_equal(a[i], e)
    }
    assert_equal(0, i)

    a = @cls[]
    i = 0
    a.reverse_each { |e|
      assert(false, "Never get here")
    }
    assert_equal(0, i)
  end

  def test_rindex
    a = @cls[ 'cat', 99, /a/, 99, [ 1, 2, 3] ]
    assert_equal(0, a.rindex('cat'))
    assert_equal(3, a.rindex(99))
    assert_equal(4, a.rindex([1,2,3]))
    assert_nil(a.rindex('ca'))
    assert_nil(a.rindex([1,2]))

    assert_equal(3, a.rindex(99) {|x| x == [1,2,3] })
  end

  def test_shift
    a = @cls[ 'cat', 'dog' ]
    assert_equal('cat', a.shift)
    assert_equal(@cls['dog'], a)
    assert_equal('dog', a.shift)
    assert_equal(@cls[], a)
    assert_nil(a.shift)
    assert_equal(@cls[], a)
  end

  def test_size
    assert_equal(0,   @cls[].size)
    assert_equal(1,   @cls[1].size)
    assert_equal(100, @cls[*(0..99).to_a].size)
  end

  def test_slice
    a = @cls[*(1..100).to_a]

    assert_equal(1, a.slice(0))
    assert_equal(100, a.slice(99))
    assert_nil(a.slice(100))
    assert_equal(100, a.slice(-1))
    assert_equal(99,  a.slice(-2))
    assert_equal(1,   a.slice(-100))
    assert_nil(a.slice(-101))

    assert_equal(@cls[1],   a.slice(0,1))
    assert_equal(@cls[100], a.slice(99,1))
    assert_equal(@cls[],    a.slice(100,1))
    assert_equal(@cls[100], a.slice(99,100))
    assert_equal(@cls[100], a.slice(-1,1))
    assert_equal(@cls[99],  a.slice(-2,1))

    assert_equal(@cls[10, 11, 12], a.slice(9, 3))
    assert_equal(@cls[10, 11, 12], a.slice(-91, 3))

    assert_nil(a.slice(-101, 2))

    assert_equal(@cls[1],   a.slice(0..0))
    assert_equal(@cls[100], a.slice(99..99))
    assert_equal(@cls[],    a.slice(100..100))
    assert_equal(@cls[100], a.slice(99..200))
    assert_equal(@cls[100], a.slice(-1..-1))
    assert_equal(@cls[99],  a.slice(-2..-2))

    assert_equal(@cls[10, 11, 12], a.slice(9..11))
    assert_equal(@cls[10, 11, 12], a.slice(-91..-89))

    assert_nil(a.slice(-101..-1))

    assert_nil(a.slice(10, -3))
    # Ruby 1.8 feature change:
    # Array#slice[size..x] always returns [].
    #assert_nil(a.slice(10..7))
    assert_equal @cls[], a.slice(10..7)
  end

  def test_slice!
    a = @cls[1, 2, 3, 4, 5]
    assert_equal(3, a.slice!(2))
    assert_equal(@cls[1, 2, 4, 5], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(4, a.slice!(-2))
    assert_equal(@cls[1, 2, 3, 5], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(@cls[3,4], a.slice!(2,2))
    assert_equal(@cls[1, 2, 5], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(@cls[4,5], a.slice!(-2,2))
    assert_equal(@cls[1, 2, 3], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(@cls[3,4], a.slice!(2..3))
    assert_equal(@cls[1, 2, 5], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(nil, a.slice!(20))
    assert_equal(@cls[1, 2, 3, 4, 5], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(nil, a.slice!(-6))
    assert_equal(@cls[1, 2, 3, 4, 5], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(nil, a.slice!(-6..4))
    assert_equal(@cls[1, 2, 3, 4, 5], a)

    a = @cls[1, 2, 3, 4, 5]
    assert_equal(nil, a.slice!(-6,2))
    assert_equal(@cls[1, 2, 3, 4, 5], a)
  end

  def test_sort
    a = @cls[ 4, 1, 2, 3 ]
    assert_equal(@cls[1, 2, 3, 4], a.sort)
    assert_equal(@cls[4, 1, 2, 3], a)

    assert_equal(@cls[4, 3, 2, 1], a.sort { |x, y| y <=> x} )
    assert_equal(@cls[4, 1, 2, 3], a)

    a.fill(1)
    assert_equal(@cls[1, 1, 1, 1], a.sort)

    assert_equal(@cls[], @cls[].sort)
  end

  def test_sort!
    a = @cls[ 4, 1, 2, 3 ]
    assert_equal(@cls[1, 2, 3, 4], a.sort!)
    assert_equal(@cls[1, 2, 3, 4], a)

    assert_equal(@cls[4, 3, 2, 1], a.sort! { |x, y| y <=> x} )
    assert_equal(@cls[4, 3, 2, 1], a)

    a.fill(1)
    assert_equal(@cls[1, 1, 1, 1], a.sort!)

    assert_equal(@cls[1], @cls[1].sort!)
    assert_equal(@cls[], @cls[].sort!)

    a = @cls[4, 3, 2, 1]
    a.sort! {|m, n| a.replace([9, 8, 7, 6]); m <=> n }
    assert_equal([1, 2, 3, 4], a)

    a = @cls[4, 3, 2, 1]
    a.sort! {|m, n| a.replace([9, 8, 7]); m <=> n }
    assert_equal([1, 2, 3, 4], a)
  end

  def test_sort_with_callcc
    respond_to?(:callcc, true) or require 'continuation'
    n = 1000
    cont = nil
    ary = (1..100).to_a
    begin
      ary.sort! {|a,b|
        callcc {|k| cont = k} unless cont
        assert_equal(100, ary.size, '[ruby-core:16679]')
        a <=> b
      }
    rescue => e
    end
    n -= 1
    cont.call if 0 < n
    assert_instance_of(RuntimeError, e, '[ruby-core:16679]')
    assert_match(/reentered/, e.message, '[ruby-core:16679]')
  end

  def test_sort_with_replace
    xary = (1..100).to_a
    100.times do
      ary = (1..100).to_a
      ary.sort! {|a,b| ary.replace(xary); a <=> b}
      GC.start
      assert_equal(xary, ary, '[ruby-dev:34732]')
    end
  end

  def test_to_a
    a = @cls[ 1, 2, 3 ]
    a_id = a.__id__
    assert_equal(a, a.to_a)
    assert_equal(a_id, a.to_a.__id__)
  end

  def test_to_ary
    a = [ 1, 2, 3 ]
    b = @cls[*a]

    a_id = a.__id__
    assert_equal(a, b.to_ary)
    if (@cls == Array)
      assert_equal(a_id, a.to_ary.__id__)
    end
  end

  def test_to_s
    $, = ""
    a = @cls[]
    assert_equal("[]", a.to_s)

    $, = ""
    a = @cls[1, 2]
    assert_equal("[1, 2]", a.to_s)

    $, = ""
    a = @cls[1, 2, 3]
    assert_equal("[1, 2, 3]", a.to_s)

    $, = ":"
    a = @cls[1, 2, 3]
    assert_equal("[1, 2, 3]", a.to_s)
  ensure
    $, = nil
  end

  def test_uniq
    a = @cls[ 1, 2, 3, 2, 1, 2, 3, 4, nil ]
    b = a.dup
    assert_equal(@cls[1, 2, 3, 4, nil], a.uniq)
    assert_equal(b, a)

    c = @cls["a:def", "a:xyz", "b:abc", "b:xyz", "c:jkl"]
    d = c.dup
    assert_equal(@cls[ "a:def", "b:abc", "c:jkl" ], c.uniq {|s| s[/^\w+/]})
    assert_equal(d, c)

    assert_equal(@cls[1, 2, 3], @cls[1, 2, 3].uniq)
  end

  def test_uniq!
    a = @cls[ 1, 2, 3, 2, 1, 2, 3, 4, nil ]
    assert_equal(@cls[1, 2, 3, 4, nil], a.uniq!)
    assert_equal(@cls[1, 2, 3, 4, nil], a)

    c = @cls["a:def", "a:xyz", "b:abc", "b:xyz", "c:jkl"]
    assert_equal(@cls[ "a:def", "b:abc", "c:jkl" ], c.uniq! {|s| s[/^\w+/]})
    assert_equal(@cls[ "a:def", "b:abc", "c:jkl" ], c)

    c = @cls["a:def", "b:abc", "c:jkl"]
    assert_equal(nil, c.uniq! {|s| s[/^\w+/]})
    assert_equal(@cls[ "a:def", "b:abc", "c:jkl" ], c)

    assert_nil(@cls[1, 2, 3].uniq!)
  end

  def test_unshift
    a = @cls[]
    assert_equal(@cls['cat'], a.unshift('cat'))
    assert_equal(@cls['dog', 'cat'], a.unshift('dog'))
    assert_equal(@cls[nil, 'dog', 'cat'], a.unshift(nil))
    assert_equal(@cls[@cls[1,2], nil, 'dog', 'cat'], a.unshift(@cls[1, 2]))
  end

  def test_OR # '|'
    assert_equal(@cls[],  @cls[]  | @cls[])
    assert_equal(@cls[1], @cls[1] | @cls[])
    assert_equal(@cls[1], @cls[]  | @cls[1])
    assert_equal(@cls[1], @cls[1] | @cls[1])

    assert_equal(@cls[1,2], @cls[1] | @cls[2])
    assert_equal(@cls[1,2], @cls[1, 1] | @cls[2, 2])
    assert_equal(@cls[1,2], @cls[1, 2] | @cls[1, 2])
  end

  def test_combination
    assert_equal(@cls[[]], @cls[1,2,3,4].combination(0).to_a)
    assert_equal(@cls[[1],[2],[3],[4]], @cls[1,2,3,4].combination(1).to_a)
    assert_equal(@cls[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]], @cls[1,2,3,4].combination(2).to_a)
    assert_equal(@cls[[1,2,3],[1,2,4],[1,3,4],[2,3,4]], @cls[1,2,3,4].combination(3).to_a)
    assert_equal(@cls[[1,2,3,4]], @cls[1,2,3,4].combination(4).to_a)
    assert_equal(@cls[], @cls[1,2,3,4].combination(5).to_a)
  end

  def test_product
    assert_equal(@cls[[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]],
                 @cls[1,2,3].product([4,5]))
    assert_equal(@cls[[1,1],[1,2],[2,1],[2,2]], @cls[1,2].product([1,2]))

    assert_equal(@cls[[1,3,5],[1,3,6],[1,4,5],[1,4,6],
                   [2,3,5],[2,3,6],[2,4,5],[2,4,6]],
                 @cls[1,2].product([3,4],[5,6]))
    assert_equal(@cls[[1],[2]], @cls[1,2].product)
    assert_equal(@cls[], @cls[1,2].product([]))
  end

  def test_permutation
    a = @cls[1,2,3]
    assert_equal(@cls[[]], a.permutation(0).to_a)
    assert_equal(@cls[[1],[2],[3]], a.permutation(1).to_a.sort)
    assert_equal(@cls[[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]],
                 a.permutation(2).to_a.sort)
    assert_equal(@cls[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
                 a.permutation(3).sort.to_a)
    assert_equal(@cls[], a.permutation(4).to_a)
    assert_equal(@cls[], a.permutation(-1).to_a)
    assert_equal("abcde".each_char.to_a.permutation(5).sort,
                 "edcba".each_char.to_a.permutation(5).sort)
    assert_equal(@cls[].permutation(0).to_a, @cls[[]])

    a = @cls[1, 2, 3, 4]
    b = @cls[]
    a.permutation {|x| b << x; a.replace(@cls[9, 8, 7, 6]) }
    assert_equal(@cls[9, 8, 7, 6], a)
    assert_equal(@cls[1, 2, 3, 4].permutation.to_a, b)
  end

  def test_take
    assert_equal([1,2,3], [1,2,3,4,5,0].take(3))
    assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].take(-1) }
    assert_equal([1,2], [1,2].take(1000000000), '[ruby-dev:34123]')
  end

  def test_take_while
    assert_equal([1,2], [1,2,3,4,5,0].take_while {|i| i < 3 })
  end

  def test_drop
    assert_equal([4,5,0], [1,2,3,4,5,0].drop(3))
    assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].drop(-1) }
    assert_equal([], [1,2].drop(1000000000), '[ruby-dev:34123]')
  end

  def test_drop_while
    assert_equal([3,4,5,0], [1,2,3,4,5,0].drop_while {|i| i < 3 })
  end

  def test_modify_check
    a = []
    a.freeze
    assert_raise(RuntimeError) { a.shift }
    a = [1, 2]
    assert_raise(SecurityError) do
      Thread.new do
        $SAFE = 4
       a.shift
      end.value
    end
  end

  LONGP = [127, 63, 31, 15, 7].map {|x| 2**x-1 }.find do |x|
    begin
      [].first(x)
    rescue ArgumentError
      true
    rescue RangeError
      false
    end
  end

  def test_ary_new
    assert_raise(ArgumentError) { [].to_enum.first(-1) }
    assert_raise(ArgumentError) { [].to_enum.first(LONGP) }
  end

  def test_try_convert
    assert_equal([1], Array.try_convert([1]))
    assert_equal(nil, Array.try_convert("1"))
  end

  def test_initialize
    assert_nothing_raised { [].instance_eval { initialize } }
    assert_nothing_raised { Array.new { } }
    assert_equal([1, 2, 3], Array.new([1, 2, 3]))
    assert_raise(ArgumentError) { Array.new(-1, 1) }
    assert_raise(ArgumentError) { Array.new(LONGP, 1) }
    assert_equal([1, 1, 1], Array.new(3, 1))
    assert_equal([1, 1, 1], Array.new(3) { 1 })
    assert_equal([1, 1, 1], Array.new(3, 1) { 1 })
  end

  def test_aset
    assert_raise(IndexError) { [0][-2] = 1 }
    assert_raise(IndexError) { [0][LONGP] = 2 }
    assert_raise(IndexError) { [0][(LONGP + 1) / 2 - 1] = 2 }
    a = [0]
    a[2] = 4
    assert_equal([0, nil, 4], a)
    assert_raise(ArgumentError) { [0][0, 0, 0] = 0 }
  end

  def test_first2
    assert_equal([0], [0].first(2))
    assert_raise(ArgumentError) { [0].first(-1) }
  end

  def test_shift2
    assert_equal(0, ([0] * 16).shift)
    # check
    a = [0, 1, 2]
    a[3] = 3
    a.shift(2)
    assert_equal([2, 3], a)
  end

  def test_unshift2
    Struct.new(:a, :b, :c)
  end

  def test_aref
    assert_raise(ArgumentError) { [][0, 0, 0] }
  end

  def test_fetch
    assert_equal(1, [].fetch(0, 0) { 1 })
    assert_equal(1, [0, 1].fetch(-1))
    assert_raise(IndexError) { [0, 1].fetch(2) }
    assert_raise(IndexError) { [0, 1].fetch(-3) }
    assert_equal(2, [0, 1].fetch(2, 2))
  end

  def test_index2
    a = [0, 1, 2]
    assert_equal(a, a.index.to_a)
    assert_equal(1, a.index {|x| x == 1 })
  end

  def test_rindex2
    a = [0, 1, 2]
    assert_equal([2, 1, 0], a.rindex.to_a)
    assert_equal(1, a.rindex {|x| x == 1 })

    a = [0, 1]
    e = a.rindex
    assert_equal(1, e.next)
    a.clear
    assert_raise(StopIteration) { e.next }

    o = Object.new
    class << o; self; end.class_eval do
      define_method(:==) {|x| a.clear; false }
    end
    a = [nil, o]
    assert_equal(nil, a.rindex(0))
  end

  def test_ary_to_ary
    o = Object.new
    def o.to_ary; [1, 2, 3]; end
    a, b, c = o
    assert_equal([1, 2, 3], [a, b, c])
  end

  def test_splice
    a = [0]
    assert_raise(IndexError) { a[-2, 0] = nil }
  end

  def test_insert
    a = [0]
    assert_equal([0], a.insert(1))
    assert_equal([0, 1], a.insert(1, 1))
    assert_raise(ArgumentError) { a.insert }
    assert_equal([0, 1, 2], a.insert(-1, 2))
    assert_equal([0, 1, 3, 2], a.insert(-2, 3))
  end

  def test_join2
    a = []
    a << a
    assert_raise(ArgumentError){a.join}

    def (a = Object.new).to_a
      [self]
    end
    assert_raise(ArgumentError, '[ruby-core:24150]'){[a].join}
    assert_equal("12345", [1,[2,[3,4],5]].join)
  end

  def test_to_a2
    klass = Class.new(Array)
    a = klass.new.to_a
    assert_equal([], a)
    assert_equal(Array, a.class)
  end

  def test_values_at2
    a = [0, 1, 2, 3, 4, 5]
    assert_equal([1, 2, 3], a.values_at(1..3))
    assert_equal([], a.values_at(7..8))
    assert_equal([nil], a.values_at(2**31-1))
  end

  def test_select
    assert_equal([0, 2], [0, 1, 2, 3].select {|x| x % 2 == 0 })
  end

  def test_delete2
    a = [0] * 1024 + [1] + [0] * 1024
    a.delete(0)
    assert_equal([1], a)
  end

  def test_reject
    assert_equal([1, 3], [0, 1, 2, 3].reject {|x| x % 2 == 0 })
  end

  def test_zip
    assert_equal([[1, :a, "a"], [2, :b, "b"], [3, nil, "c"]],
      [1, 2, 3].zip([:a, :b], ["a", "b", "c", "d"]))
    a = []
    [1, 2, 3].zip([:a, :b], ["a", "b", "c", "d"]) {|x| a << x }
    assert_equal([[1, :a, "a"], [2, :b, "b"], [3, nil, "c"]], a)

    ary = Object.new
    def ary.to_a;   [1, 2]; end
    assert_raise(NoMethodError){ %w(a b).zip(ary) }
    def ary.each; [3, 4].each{|e|yield e}; end
    assert_equal([['a', 3], ['b', 4]], %w(a b).zip(ary))
    def ary.to_ary; [5, 6]; end
    assert_equal([['a', 5], ['b', 6]], %w(a b).zip(ary))
  end

  def test_transpose
    assert_equal([[1, :a], [2, :b], [3, :c]],
      [[1, 2, 3], [:a, :b, :c]].transpose)
    assert_raise(IndexError) { [[1, 2, 3], [:a, :b]].transpose }
  end

  def test_clear2
    assert_equal([], ([0] * 1024).clear)
  end

  def test_fill2
    assert_raise(ArgumentError) { [].fill(0, 1, LONGP) }
  end

  def test_times
    assert_raise(ArgumentError) { [0, 0, 0, 0] * ((LONGP + 1) / 4) }
  end

  def test_equal
    o = Object.new
    def o.to_ary; end
    def o.==(x); :foo; end
    assert(:foo, [0, 1, 2] == o)
    assert([0, 1, 2] != [0, 1, 3])
  end

  def test_hash2
    a = []
    a << a
    assert_equal([[a]].hash, a.hash)
    assert_not_equal([a, a].hash, a.hash) # Implementation dependent
  end

  def test_flatten2
    a = []
    a << a
    assert_raise(ArgumentError) { a.flatten }
  end

  def test_shuffle
    100.times do
      assert_equal([0, 1, 2], [2, 1, 0].shuffle.sort)
    end
  end

  def test_sample
    100.times do
      assert([0, 1, 2].include?([2, 1, 0].sample))
      samples = [2, 1, 0].sample(2)
      samples.each{|sample|
        assert([0, 1, 2].include?(sample))
      }
    end

    srand(0)
    a = (1..18).to_a
    (0..20).each do |n|
      10000.times do
        b = a.sample(n)
        assert_equal([n, 18].min, b.uniq.size)
        assert_equal(a, (a | b).sort)
        assert_equal(b.sort, (a & b).sort)
      end

      h = Hash.new(0)
      10000.times do
        a.sample(n).each {|x| h[x] += 1 }
      end
      assert_operator(h.values.min * 2, :>=, h.values.max) if n != 0
    end

    assert_raise(ArgumentError, '[ruby-core:23374]') {[1, 2].sample(-1)}
  end

  def test_cycle
    a = []
    [0, 1, 2].cycle do |i|
      a << i
      break if a.size == 10
    end
    assert_equal([0, 1, 2, 0, 1, 2, 0, 1, 2, 0], a)

    a = [0, 1, 2]
    assert_nil(a.cycle { a.clear })

    a = []
    [0, 1, 2].cycle(3) {|i| a << i }
    assert_equal([0, 1, 2, 0, 1, 2, 0, 1, 2], a)
  end

  def test_reverse_each2
    a = [0, 1, 2, 3, 4, 5]
    r = []
    a.reverse_each do |x|
      r << x
      a.pop
      a.pop
    end
    assert_equal([5, 3, 1], r)
  end

  def test_combination2
    assert_raise(RangeError) do
      (0..100).to_a.combination(50) {}
    end
  end

  def test_product2
    a = (0..100).to_a
    assert_raise(RangeError) do
      a.product(a, a, a, a, a, a, a, a, a, a) {}
    end
  end

  class Array2 < Array
  end

  def test_array_subclass
    assert_equal(Array2, Array2[1,2,3].uniq.class, "[ruby-dev:34581]")
    assert_equal(Array2, Array2[1,2][0,1].class) # embeded
    assert_equal(Array2, Array2[*(1..100)][1..99].class) #not embeded
  end

  def test_inspect
    a = @cls[1, 2, 3]
    a.taint
    a.untrust
    s = a.inspect
    assert_equal(true, s.tainted?)
    assert_equal(true, s.untrusted?)
  end

  def test_initialize2
    a = [1] * 1000
    a.instance_eval { initialize }
    assert_equal([], a)
  end

  def test_shift_shared_ary
    a = (1..100).to_a
    b = []
    b.replace(a)
    assert_equal((1..10).to_a, a.shift(10))
    assert_equal((11..100).to_a, a)
  end

  def test_replace_shared_ary
    a = [1] * 100
    b = []
    b.replace(a)
    a.replace([1, 2, 3])
    assert_equal([1, 2, 3], a)
    assert_equal([1] * 100, b)
  end

  def test_fill_negative_length
    a = (1..10).to_a
    a.fill(:foo, 5, -3)
    assert_equal((1..10).to_a, a)
  end

  def test_slice_freezed_array
    a = [1,2,3,4,5].freeze
    assert_equal([1,2,3,4], a[0,4])
    assert_equal([2,3,4,5], a[1,4])
  end

  def test_sort_by!
    a = [1,3,5,2,4]
    a.sort_by! {|x| -x }
    assert_equal([5,4,3,2,1], a)
  end
end