public void EncoderFallbackExceptions ()
		{

			EncoderFallbackExceptionTest [] tests = new EncoderFallbackExceptionTest []
			{
				/* #1  */ new EncoderFallbackExceptionTest ( "Zero \u0000.",                                   new int [] { }),
				/* #2  */ new EncoderFallbackExceptionTest ( "Last before leads \uD7FF.",                      new int [] { }),
				/* #3  */ new EncoderFallbackExceptionTest ( "Using lead \uD800 without a surrogate.",         new int [] { 11 }),
				/* #4  */ new EncoderFallbackExceptionTest ( "Using lead \uD877 without a surrogate.",         new int [] { 11 }),
				/* #5  */ new EncoderFallbackExceptionTest ( "Using lead \uDBFF without a surrogate.",         new int [] { 11 }),
				/* #6  */ new EncoderFallbackExceptionTest ( "Using trail \uDC00 without a lead.",             new int [] { 12 }),
				/* #7  */ new EncoderFallbackExceptionTest ( "Using trail \uDBFF without a lead.",             new int [] { 12 }),
				/* #8  */ new EncoderFallbackExceptionTest ( "First-plane 2nd block \uE000.",                  new int [] { }),
				/* #9  */ new EncoderFallbackExceptionTest ( "First-plane 2nd block \uFFFF.",                  new int [] { }),
				/* #10 */ new EncoderFallbackExceptionTest ( "Playing with first surrogate \uD800\uDC00.",     new int [] { }),
				/* #11 */ new EncoderFallbackExceptionTest ( "Playing before first surrogate \uD800\uDBFF.",   new int [] { 31, 32 }),
				/* #12 */ new EncoderFallbackExceptionTest ( "Playing with last of first plane \uD800\uDFFF.", new int [] { }),
				/* #13 */ new EncoderFallbackExceptionTest ( "Playing with first of last plane \uDBFF\uDC00.", new int [] { }),
				/* #14 */ new EncoderFallbackExceptionTest ( "Playing with last surrogate \uDBFF\uDFFF.",      new int [] { }),
				/* #15 */ new EncoderFallbackExceptionTest ( "Playing after last surrogate \uDBFF\uE000.",     new int [] { 29 }),
				/* #16 */ new EncoderFallbackExceptionTest ( "Incomplete string \uD800",                       new int [] { 18 }),
				/* #17 */ new EncoderFallbackExceptionTest ( "Horrible thing \uD800\uD800.",                   new int [] { 15, 16 }),
			};
			Encoding utf8 = Encoding.GetEncoding (
						"utf-8",
						new EncoderExceptionFallback(),
						new DecoderExceptionFallback());
			Encoder enc = utf8.GetEncoder ();
			byte [] bytes;

			for(int t = 0; t < tests.Length; t++) {
				bytes = new byte [utf8.GetMaxByteCount (tests[t].str.Length)];

				// #1 complete conversion
				EncoderFallbackExceptions_GetBytes (bytes, t+1, enc, tests[t]);

				// #2 convert in two rounds
				for (int bs = 1; bs <= tests[t].str.Length; bs++)
					EncoderFallbackExceptions_Convert (bytes, t+1, enc, tests[t], bs);
			}
		}
		// try to encode some bytes at once with GetBytes
		private void EncoderFallbackExceptions_GetBytes (
			byte [] bytes,
			int testno,
			Encoder enc,
			EncoderFallbackExceptionTest t)
		{
			try {
				enc.GetBytes (
					t.str.ToCharArray (), 0, t.str.Length,
					bytes, 0, true);
				Assert.IsTrue (
					t.eindex.Length == 0,
					String.Format (
						"test#{0}-1: UNEXPECTED SUCCESS",
						testno));
			} catch(EncoderFallbackException ex) {
				Assert.IsTrue (
					t.eindex.Length > 0,
					String.Format (
						"test#{0}-1: UNEXPECTED FAIL",
						testno));
				Assert.IsTrue (
					ex.Index == t.eindex[0],
					String.Format (
						"test#{0}-1: Expected exception at {1} not {2}.",
						testno, t.eindex[0], ex.Index));
				Assert.IsTrue (
					!ex.IsUnknownSurrogate (),
					String.Format (
						"test#{0}-1: Expected false not {1} in IsUnknownSurrogate().",
						testno,
						ex.IsUnknownSurrogate ()));
				// NOTE: I know that in the previous check we
				// have asserted that ex.IsUnknownSurrogate()
				// is always false, but this does not mean that
				// we don't have to take in consideration its
				// real value for the next check.
				if (ex.IsUnknownSurrogate ())
					Assert.IsTrue (
						ex.CharUnknownHigh == t.str[ex.Index]
						&& ex.CharUnknownLow == t.str[ex.Index + 1],
						String.Format (
							"test#{0}-1: expected ({1:X}, {2:X}) not ({3:X}, {4:X}).",
							testno,
							t.str[ex.Index],
							t.str[ex.Index + 1],
							ex.CharUnknownHigh,
							ex.CharUnknownLow));
				else
					Assert.IsTrue (
						ex.CharUnknown == t.str[ex.Index],
						String.Format (
							"test#{0}-1: expected ({1:X}) not ({2:X}).",
							testno,
							t.str[ex.Index],
							ex.CharUnknown));
				enc.Reset ();
			}
		}
		private void EncoderFallbackExceptions_Convert (
			byte [] bytes,
			int testno,
			Encoder enc,
			EncoderFallbackExceptionTest t,
			int block_size)
		{
			int charsUsed, bytesUsed;
			bool completed;

			int ce = 0; // current exception

			for (int c = 0; c < t.str.Length; ) {
				//Console.WriteLine ("test#{0}-2-{1}: c={2}", testno, block_size, c);
				try {
					int bu = c + block_size > t.str.Length
							? t.str.Length - c
							: block_size;
					enc.Convert (
						t.str.ToCharArray (), c, bu,
						bytes, 0, bytes.Length,
						c + bu >= t.str.Length,
						out charsUsed, out bytesUsed,
						out completed);
					c += charsUsed;
				} catch (EncoderFallbackException ex) {
					//Console.WriteLine (
					//	"test#{0}-2-{1}#{2}: Exception (Index={3}, UnknownSurrogate={4})",
					//	testno, block_size, ce,
					//	ex.Index, ex.IsUnknownSurrogate ());
					Assert.IsTrue (
						ce < t.eindex.Length,
						String.Format (
							"test#{0}-2-{1}#{2}: UNEXPECTED EXCEPTION (Index={3}, UnknownSurrogate={4})",
							testno, block_size, ce,
							ex.Index,
							ex.IsUnknownSurrogate ()));
					Assert.IsTrue (
						ex.Index + c == t.eindex[ce],
						String.Format (
							"test#{0}-2-{1}#{2}: Expected exception at {3} not {4}.",
							testno, block_size, ce,
							t.eindex[ce],
							ex.Index + c));
					Assert.IsTrue (
						!ex.IsUnknownSurrogate (),
						String.Format (
							"test#{0}-2-{1}#{2}: Expected false not {3} in IsUnknownSurrogate().",
							testno, block_size, ce,
							ex.IsUnknownSurrogate ()));
					if (ex.IsUnknownSurrogate ()) {
						Assert.IsTrue (
							ex.CharUnknownHigh == t.str[ex.Index + c]
							&& ex.CharUnknownLow == t.str[ex.Index + c + 1],
							String.Format (
								"test#{0}-2-{1}#{2}: expected ({3:X}, {4:X}) not ({5:X}, {6:X}).",
								testno, block_size, ce,
								t.str[ex.Index + c], t.str[ex.Index + c + 1],
								ex.CharUnknownHigh, ex.CharUnknownLow));
						c += ex.Index + 2;
					} else {
						Assert.IsTrue (
							ex.CharUnknown == t.str[ex.Index + c],
							String.Format (
								"test#{0}-2-{1}#{2}: expected ({3:X}) not ({4:X}).",
								testno, block_size, ce,
								t.str[ex.Index + c],
								ex.CharUnknown));
						c += ex.Index + 1;
					}
					enc.Reset ();
					ce++;
				}
			}
			Assert.IsTrue (
				ce == t.eindex.Length,
				String.Format (
					"test#{0}-2-{1}: UNEXPECTED SUCCESS (expected {2} exceptions, but happened {3})",
					testno, block_size, t.eindex.Length, ce));
		}