...

Source file src/text/tabwriter/tabwriter_test.go

Documentation: text/tabwriter

		 1  // Copyright 2009 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  package tabwriter_test
		 6  
		 7  import (
		 8  	"bytes"
		 9  	"fmt"
		10  	"io"
		11  	"testing"
		12  	. "text/tabwriter"
		13  )
		14  
		15  type buffer struct {
		16  	a []byte
		17  }
		18  
		19  func (b *buffer) init(n int) { b.a = make([]byte, 0, n) }
		20  
		21  func (b *buffer) clear() { b.a = b.a[0:0] }
		22  
		23  func (b *buffer) Write(buf []byte) (written int, err error) {
		24  	n := len(b.a)
		25  	m := len(buf)
		26  	if n+m <= cap(b.a) {
		27  		b.a = b.a[0 : n+m]
		28  		for i := 0; i < m; i++ {
		29  			b.a[n+i] = buf[i]
		30  		}
		31  	} else {
		32  		panic("buffer.Write: buffer too small")
		33  	}
		34  	return len(buf), nil
		35  }
		36  
		37  func (b *buffer) String() string { return string(b.a) }
		38  
		39  func write(t *testing.T, testname string, w *Writer, src string) {
		40  	written, err := io.WriteString(w, src)
		41  	if err != nil {
		42  		t.Errorf("--- test: %s\n--- src:\n%q\n--- write error: %v\n", testname, src, err)
		43  	}
		44  	if written != len(src) {
		45  		t.Errorf("--- test: %s\n--- src:\n%q\n--- written = %d, len(src) = %d\n", testname, src, written, len(src))
		46  	}
		47  }
		48  
		49  func verify(t *testing.T, testname string, w *Writer, b *buffer, src, expected string) {
		50  	err := w.Flush()
		51  	if err != nil {
		52  		t.Errorf("--- test: %s\n--- src:\n%q\n--- flush error: %v\n", testname, src, err)
		53  	}
		54  
		55  	res := b.String()
		56  	if res != expected {
		57  		t.Errorf("--- test: %s\n--- src:\n%q\n--- found:\n%q\n--- expected:\n%q\n", testname, src, res, expected)
		58  	}
		59  }
		60  
		61  func check(t *testing.T, testname string, minwidth, tabwidth, padding int, padchar byte, flags uint, src, expected string) {
		62  	var b buffer
		63  	b.init(1000)
		64  
		65  	var w Writer
		66  	w.Init(&b, minwidth, tabwidth, padding, padchar, flags)
		67  
		68  	// write all at once
		69  	title := testname + " (written all at once)"
		70  	b.clear()
		71  	write(t, title, &w, src)
		72  	verify(t, title, &w, &b, src, expected)
		73  
		74  	// write byte-by-byte
		75  	title = testname + " (written byte-by-byte)"
		76  	b.clear()
		77  	for i := 0; i < len(src); i++ {
		78  		write(t, title, &w, src[i:i+1])
		79  	}
		80  	verify(t, title, &w, &b, src, expected)
		81  
		82  	// write using Fibonacci slice sizes
		83  	title = testname + " (written in fibonacci slices)"
		84  	b.clear()
		85  	for i, d := 0, 0; i < len(src); {
		86  		write(t, title, &w, src[i:i+d])
		87  		i, d = i+d, d+1
		88  		if i+d > len(src) {
		89  			d = len(src) - i
		90  		}
		91  	}
		92  	verify(t, title, &w, &b, src, expected)
		93  }
		94  
		95  var tests = []struct {
		96  	testname										string
		97  	minwidth, tabwidth, padding int
		98  	padchar										 byte
		99  	flags											 uint
	 100  	src, expected							 string
	 101  }{
	 102  	{
	 103  		"1a",
	 104  		8, 0, 1, '.', 0,
	 105  		"",
	 106  		"",
	 107  	},
	 108  
	 109  	{
	 110  		"1a debug",
	 111  		8, 0, 1, '.', Debug,
	 112  		"",
	 113  		"",
	 114  	},
	 115  
	 116  	{
	 117  		"1b esc stripped",
	 118  		8, 0, 1, '.', StripEscape,
	 119  		"\xff\xff",
	 120  		"",
	 121  	},
	 122  
	 123  	{
	 124  		"1b esc",
	 125  		8, 0, 1, '.', 0,
	 126  		"\xff\xff",
	 127  		"\xff\xff",
	 128  	},
	 129  
	 130  	{
	 131  		"1c esc stripped",
	 132  		8, 0, 1, '.', StripEscape,
	 133  		"\xff\t\xff",
	 134  		"\t",
	 135  	},
	 136  
	 137  	{
	 138  		"1c esc",
	 139  		8, 0, 1, '.', 0,
	 140  		"\xff\t\xff",
	 141  		"\xff\t\xff",
	 142  	},
	 143  
	 144  	{
	 145  		"1d esc stripped",
	 146  		8, 0, 1, '.', StripEscape,
	 147  		"\xff\"foo\t\n\tbar\"\xff",
	 148  		"\"foo\t\n\tbar\"",
	 149  	},
	 150  
	 151  	{
	 152  		"1d esc",
	 153  		8, 0, 1, '.', 0,
	 154  		"\xff\"foo\t\n\tbar\"\xff",
	 155  		"\xff\"foo\t\n\tbar\"\xff",
	 156  	},
	 157  
	 158  	{
	 159  		"1e esc stripped",
	 160  		8, 0, 1, '.', StripEscape,
	 161  		"abc\xff\tdef", // unterminated escape
	 162  		"abc\tdef",
	 163  	},
	 164  
	 165  	{
	 166  		"1e esc",
	 167  		8, 0, 1, '.', 0,
	 168  		"abc\xff\tdef", // unterminated escape
	 169  		"abc\xff\tdef",
	 170  	},
	 171  
	 172  	{
	 173  		"2",
	 174  		8, 0, 1, '.', 0,
	 175  		"\n\n\n",
	 176  		"\n\n\n",
	 177  	},
	 178  
	 179  	{
	 180  		"3",
	 181  		8, 0, 1, '.', 0,
	 182  		"a\nb\nc",
	 183  		"a\nb\nc",
	 184  	},
	 185  
	 186  	{
	 187  		"4a",
	 188  		8, 0, 1, '.', 0,
	 189  		"\t", // '\t' terminates an empty cell on last line - nothing to print
	 190  		"",
	 191  	},
	 192  
	 193  	{
	 194  		"4b",
	 195  		8, 0, 1, '.', AlignRight,
	 196  		"\t", // '\t' terminates an empty cell on last line - nothing to print
	 197  		"",
	 198  	},
	 199  
	 200  	{
	 201  		"5",
	 202  		8, 0, 1, '.', 0,
	 203  		"*\t*",
	 204  		"*.......*",
	 205  	},
	 206  
	 207  	{
	 208  		"5b",
	 209  		8, 0, 1, '.', 0,
	 210  		"*\t*\n",
	 211  		"*.......*\n",
	 212  	},
	 213  
	 214  	{
	 215  		"5c",
	 216  		8, 0, 1, '.', 0,
	 217  		"*\t*\t",
	 218  		"*.......*",
	 219  	},
	 220  
	 221  	{
	 222  		"5c debug",
	 223  		8, 0, 1, '.', Debug,
	 224  		"*\t*\t",
	 225  		"*.......|*",
	 226  	},
	 227  
	 228  	{
	 229  		"5d",
	 230  		8, 0, 1, '.', AlignRight,
	 231  		"*\t*\t",
	 232  		".......**",
	 233  	},
	 234  
	 235  	{
	 236  		"6",
	 237  		8, 0, 1, '.', 0,
	 238  		"\t\n",
	 239  		"........\n",
	 240  	},
	 241  
	 242  	{
	 243  		"7a",
	 244  		8, 0, 1, '.', 0,
	 245  		"a) foo",
	 246  		"a) foo",
	 247  	},
	 248  
	 249  	{
	 250  		"7b",
	 251  		8, 0, 1, ' ', 0,
	 252  		"b) foo\tbar",
	 253  		"b) foo	bar",
	 254  	},
	 255  
	 256  	{
	 257  		"7c",
	 258  		8, 0, 1, '.', 0,
	 259  		"c) foo\tbar\t",
	 260  		"c) foo..bar",
	 261  	},
	 262  
	 263  	{
	 264  		"7d",
	 265  		8, 0, 1, '.', 0,
	 266  		"d) foo\tbar\n",
	 267  		"d) foo..bar\n",
	 268  	},
	 269  
	 270  	{
	 271  		"7e",
	 272  		8, 0, 1, '.', 0,
	 273  		"e) foo\tbar\t\n",
	 274  		"e) foo..bar.....\n",
	 275  	},
	 276  
	 277  	{
	 278  		"7f",
	 279  		8, 0, 1, '.', FilterHTML,
	 280  		"f) f&lt;o\t<b>bar</b>\t\n",
	 281  		"f) f&lt;o..<b>bar</b>.....\n",
	 282  	},
	 283  
	 284  	{
	 285  		"7g",
	 286  		8, 0, 1, '.', FilterHTML,
	 287  		"g) f&lt;o\t<b>bar</b>\t non-terminated entity &amp",
	 288  		"g) f&lt;o..<b>bar</b>..... non-terminated entity &amp",
	 289  	},
	 290  
	 291  	{
	 292  		"7g debug",
	 293  		8, 0, 1, '.', FilterHTML | Debug,
	 294  		"g) f&lt;o\t<b>bar</b>\t non-terminated entity &amp",
	 295  		"g) f&lt;o..|<b>bar</b>.....| non-terminated entity &amp",
	 296  	},
	 297  
	 298  	{
	 299  		"8",
	 300  		8, 0, 1, '*', 0,
	 301  		"Hello, world!\n",
	 302  		"Hello, world!\n",
	 303  	},
	 304  
	 305  	{
	 306  		"9a",
	 307  		1, 0, 0, '.', 0,
	 308  		"1\t2\t3\t4\n" +
	 309  			"11\t222\t3333\t44444\n",
	 310  
	 311  		"1.2..3...4\n" +
	 312  			"11222333344444\n",
	 313  	},
	 314  
	 315  	{
	 316  		"9b",
	 317  		1, 0, 0, '.', FilterHTML,
	 318  		"1\t2<!---\f--->\t3\t4\n" + // \f inside HTML is ignored
	 319  			"11\t222\t3333\t44444\n",
	 320  
	 321  		"1.2<!---\f--->..3...4\n" +
	 322  			"11222333344444\n",
	 323  	},
	 324  
	 325  	{
	 326  		"9c",
	 327  		1, 0, 0, '.', 0,
	 328  		"1\t2\t3\t4\f" + // \f causes a newline and flush
	 329  			"11\t222\t3333\t44444\n",
	 330  
	 331  		"1234\n" +
	 332  			"11222333344444\n",
	 333  	},
	 334  
	 335  	{
	 336  		"9c debug",
	 337  		1, 0, 0, '.', Debug,
	 338  		"1\t2\t3\t4\f" + // \f causes a newline and flush
	 339  			"11\t222\t3333\t44444\n",
	 340  
	 341  		"1|2|3|4\n" +
	 342  			"---\n" +
	 343  			"11|222|3333|44444\n",
	 344  	},
	 345  
	 346  	{
	 347  		"10a",
	 348  		5, 0, 0, '.', 0,
	 349  		"1\t2\t3\t4\n",
	 350  		"1....2....3....4\n",
	 351  	},
	 352  
	 353  	{
	 354  		"10b",
	 355  		5, 0, 0, '.', 0,
	 356  		"1\t2\t3\t4\t\n",
	 357  		"1....2....3....4....\n",
	 358  	},
	 359  
	 360  	{
	 361  		"11",
	 362  		8, 0, 1, '.', 0,
	 363  		"本\tb\tc\n" +
	 364  			"aa\t\u672c\u672c\u672c\tcccc\tddddd\n" +
	 365  			"aaa\tbbbb\n",
	 366  
	 367  		"本.......b.......c\n" +
	 368  			"aa......本本本.....cccc....ddddd\n" +
	 369  			"aaa.....bbbb\n",
	 370  	},
	 371  
	 372  	{
	 373  		"12a",
	 374  		8, 0, 1, ' ', AlignRight,
	 375  		"a\tè\tc\t\n" +
	 376  			"aa\tèèè\tcccc\tddddd\t\n" +
	 377  			"aaa\tèèèè\t\n",
	 378  
	 379  		"			 a			 è			 c\n" +
	 380  			"			aa		 èèè		cccc	 ddddd\n" +
	 381  			"		 aaa		èèèè\n",
	 382  	},
	 383  
	 384  	{
	 385  		"12b",
	 386  		2, 0, 0, ' ', 0,
	 387  		"a\tb\tc\n" +
	 388  			"aa\tbbb\tcccc\n" +
	 389  			"aaa\tbbbb\n",
	 390  
	 391  		"a	b	c\n" +
	 392  			"aa bbbcccc\n" +
	 393  			"aaabbbb\n",
	 394  	},
	 395  
	 396  	{
	 397  		"12c",
	 398  		8, 0, 1, '_', 0,
	 399  		"a\tb\tc\n" +
	 400  			"aa\tbbb\tcccc\n" +
	 401  			"aaa\tbbbb\n",
	 402  
	 403  		"a_______b_______c\n" +
	 404  			"aa______bbb_____cccc\n" +
	 405  			"aaa_____bbbb\n",
	 406  	},
	 407  
	 408  	{
	 409  		"13a",
	 410  		4, 0, 1, '-', 0,
	 411  		"4444\t日本語\t22\t1\t333\n" +
	 412  			"999999999\t22\n" +
	 413  			"7\t22\n" +
	 414  			"\t\t\t88888888\n" +
	 415  			"\n" +
	 416  			"666666\t666666\t666666\t4444\n" +
	 417  			"1\t1\t999999999\t0000000000\n",
	 418  
	 419  		"4444------日本語-22--1---333\n" +
	 420  			"999999999-22\n" +
	 421  			"7---------22\n" +
	 422  			"------------------88888888\n" +
	 423  			"\n" +
	 424  			"666666-666666-666666----4444\n" +
	 425  			"1------1------999999999-0000000000\n",
	 426  	},
	 427  
	 428  	{
	 429  		"13b",
	 430  		4, 0, 3, '.', 0,
	 431  		"4444\t333\t22\t1\t333\n" +
	 432  			"999999999\t22\n" +
	 433  			"7\t22\n" +
	 434  			"\t\t\t88888888\n" +
	 435  			"\n" +
	 436  			"666666\t666666\t666666\t4444\n" +
	 437  			"1\t1\t999999999\t0000000000\n",
	 438  
	 439  		"4444........333...22...1...333\n" +
	 440  			"999999999...22\n" +
	 441  			"7...........22\n" +
	 442  			"....................88888888\n" +
	 443  			"\n" +
	 444  			"666666...666666...666666......4444\n" +
	 445  			"1........1........999999999...0000000000\n",
	 446  	},
	 447  
	 448  	{
	 449  		"13c",
	 450  		8, 8, 1, '\t', FilterHTML,
	 451  		"4444\t333\t22\t1\t333\n" +
	 452  			"999999999\t22\n" +
	 453  			"7\t22\n" +
	 454  			"\t\t\t88888888\n" +
	 455  			"\n" +
	 456  			"666666\t666666\t666666\t4444\n" +
	 457  			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
	 458  
	 459  		"4444\t\t333\t22\t1\t333\n" +
	 460  			"999999999\t22\n" +
	 461  			"7\t\t22\n" +
	 462  			"\t\t\t\t88888888\n" +
	 463  			"\n" +
	 464  			"666666\t666666\t666666\t\t4444\n" +
	 465  			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
	 466  	},
	 467  
	 468  	{
	 469  		"14",
	 470  		1, 0, 2, ' ', AlignRight,
	 471  		".0\t.3\t2.4\t-5.1\t\n" +
	 472  			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
	 473  			"5.1\t12.0\t2.4\t-7.0\t\n" +
	 474  			".0\t0.0\t332.0\t8908.0\t\n" +
	 475  			".0\t-.3\t456.4\t22.1\t\n" +
	 476  			".0\t1.2\t44.4\t-13.3\t\t",
	 477  
	 478  		"		.0					.3		2.4		-5.1\n" +
	 479  			"	23.0	12345678.9		2.4	-989.4\n" +
	 480  			"	 5.1				12.0		2.4		-7.0\n" +
	 481  			"		.0				 0.0	332.0	8908.0\n" +
	 482  			"		.0				 -.3	456.4		22.1\n" +
	 483  			"		.0				 1.2	 44.4	 -13.3",
	 484  	},
	 485  
	 486  	{
	 487  		"14 debug",
	 488  		1, 0, 2, ' ', AlignRight | Debug,
	 489  		".0\t.3\t2.4\t-5.1\t\n" +
	 490  			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
	 491  			"5.1\t12.0\t2.4\t-7.0\t\n" +
	 492  			".0\t0.0\t332.0\t8908.0\t\n" +
	 493  			".0\t-.3\t456.4\t22.1\t\n" +
	 494  			".0\t1.2\t44.4\t-13.3\t\t",
	 495  
	 496  		"		.0|					.3|		2.4|		-5.1|\n" +
	 497  			"	23.0|	12345678.9|		2.4|	-989.4|\n" +
	 498  			"	 5.1|				12.0|		2.4|		-7.0|\n" +
	 499  			"		.0|				 0.0|	332.0|	8908.0|\n" +
	 500  			"		.0|				 -.3|	456.4|		22.1|\n" +
	 501  			"		.0|				 1.2|	 44.4|	 -13.3|",
	 502  	},
	 503  
	 504  	{
	 505  		"15a",
	 506  		4, 0, 0, '.', 0,
	 507  		"a\t\tb",
	 508  		"a.......b",
	 509  	},
	 510  
	 511  	{
	 512  		"15b",
	 513  		4, 0, 0, '.', DiscardEmptyColumns,
	 514  		"a\t\tb", // htabs - do not discard column
	 515  		"a.......b",
	 516  	},
	 517  
	 518  	{
	 519  		"15c",
	 520  		4, 0, 0, '.', DiscardEmptyColumns,
	 521  		"a\v\vb",
	 522  		"a...b",
	 523  	},
	 524  
	 525  	{
	 526  		"15d",
	 527  		4, 0, 0, '.', AlignRight | DiscardEmptyColumns,
	 528  		"a\v\vb",
	 529  		"...ab",
	 530  	},
	 531  
	 532  	{
	 533  		"16a",
	 534  		100, 100, 0, '\t', 0,
	 535  		"a\tb\t\td\n" +
	 536  			"a\tb\t\td\te\n" +
	 537  			"a\n" +
	 538  			"a\tb\tc\td\n" +
	 539  			"a\tb\tc\td\te\n",
	 540  
	 541  		"a\tb\t\td\n" +
	 542  			"a\tb\t\td\te\n" +
	 543  			"a\n" +
	 544  			"a\tb\tc\td\n" +
	 545  			"a\tb\tc\td\te\n",
	 546  	},
	 547  
	 548  	{
	 549  		"16b",
	 550  		100, 100, 0, '\t', DiscardEmptyColumns,
	 551  		"a\vb\v\vd\n" +
	 552  			"a\vb\v\vd\ve\n" +
	 553  			"a\n" +
	 554  			"a\vb\vc\vd\n" +
	 555  			"a\vb\vc\vd\ve\n",
	 556  
	 557  		"a\tb\td\n" +
	 558  			"a\tb\td\te\n" +
	 559  			"a\n" +
	 560  			"a\tb\tc\td\n" +
	 561  			"a\tb\tc\td\te\n",
	 562  	},
	 563  
	 564  	{
	 565  		"16b debug",
	 566  		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
	 567  		"a\vb\v\vd\n" +
	 568  			"a\vb\v\vd\ve\n" +
	 569  			"a\n" +
	 570  			"a\vb\vc\vd\n" +
	 571  			"a\vb\vc\vd\ve\n",
	 572  
	 573  		"a\t|b\t||d\n" +
	 574  			"a\t|b\t||d\t|e\n" +
	 575  			"a\n" +
	 576  			"a\t|b\t|c\t|d\n" +
	 577  			"a\t|b\t|c\t|d\t|e\n",
	 578  	},
	 579  
	 580  	{
	 581  		"16c",
	 582  		100, 100, 0, '\t', DiscardEmptyColumns,
	 583  		"a\tb\t\td\n" + // hard tabs - do not discard column
	 584  			"a\tb\t\td\te\n" +
	 585  			"a\n" +
	 586  			"a\tb\tc\td\n" +
	 587  			"a\tb\tc\td\te\n",
	 588  
	 589  		"a\tb\t\td\n" +
	 590  			"a\tb\t\td\te\n" +
	 591  			"a\n" +
	 592  			"a\tb\tc\td\n" +
	 593  			"a\tb\tc\td\te\n",
	 594  	},
	 595  
	 596  	{
	 597  		"16c debug",
	 598  		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
	 599  		"a\tb\t\td\n" + // hard tabs - do not discard column
	 600  			"a\tb\t\td\te\n" +
	 601  			"a\n" +
	 602  			"a\tb\tc\td\n" +
	 603  			"a\tb\tc\td\te\n",
	 604  
	 605  		"a\t|b\t|\t|d\n" +
	 606  			"a\t|b\t|\t|d\t|e\n" +
	 607  			"a\n" +
	 608  			"a\t|b\t|c\t|d\n" +
	 609  			"a\t|b\t|c\t|d\t|e\n",
	 610  	},
	 611  }
	 612  
	 613  func Test(t *testing.T) {
	 614  	for _, e := range tests {
	 615  		check(t, e.testname, e.minwidth, e.tabwidth, e.padding, e.padchar, e.flags, e.src, e.expected)
	 616  	}
	 617  }
	 618  
	 619  type panicWriter struct{}
	 620  
	 621  func (panicWriter) Write([]byte) (int, error) {
	 622  	panic("cannot write")
	 623  }
	 624  
	 625  func wantPanicString(t *testing.T, want string) {
	 626  	if e := recover(); e != nil {
	 627  		got, ok := e.(string)
	 628  		switch {
	 629  		case !ok:
	 630  			t.Errorf("got %v (%T), want panic string", e, e)
	 631  		case got != want:
	 632  			t.Errorf("wrong panic message: got %q, want %q", got, want)
	 633  		}
	 634  	}
	 635  }
	 636  
	 637  func TestPanicDuringFlush(t *testing.T) {
	 638  	defer wantPanicString(t, "tabwriter: panic during Flush")
	 639  	var p panicWriter
	 640  	w := new(Writer)
	 641  	w.Init(p, 0, 0, 5, ' ', 0)
	 642  	io.WriteString(w, "a")
	 643  	w.Flush()
	 644  	t.Errorf("failed to panic during Flush")
	 645  }
	 646  
	 647  func TestPanicDuringWrite(t *testing.T) {
	 648  	defer wantPanicString(t, "tabwriter: panic during Write")
	 649  	var p panicWriter
	 650  	w := new(Writer)
	 651  	w.Init(p, 0, 0, 5, ' ', 0)
	 652  	io.WriteString(w, "a\n\n") // the second \n triggers a call to w.Write and thus a panic
	 653  	t.Errorf("failed to panic during Write")
	 654  }
	 655  
	 656  func BenchmarkTable(b *testing.B) {
	 657  	for _, w := range [...]int{1, 10, 100} {
	 658  		// Build a line with w cells.
	 659  		line := bytes.Repeat([]byte("a\t"), w)
	 660  		line = append(line, '\n')
	 661  		for _, h := range [...]int{10, 1000, 100000} {
	 662  			b.Run(fmt.Sprintf("%dx%d", w, h), func(b *testing.B) {
	 663  				b.Run("new", func(b *testing.B) {
	 664  					b.ReportAllocs()
	 665  					for i := 0; i < b.N; i++ {
	 666  						w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
	 667  						// Write the line h times.
	 668  						for j := 0; j < h; j++ {
	 669  							w.Write(line)
	 670  						}
	 671  						w.Flush()
	 672  					}
	 673  				})
	 674  
	 675  				b.Run("reuse", func(b *testing.B) {
	 676  					b.ReportAllocs()
	 677  					w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
	 678  					for i := 0; i < b.N; i++ {
	 679  						// Write the line h times.
	 680  						for j := 0; j < h; j++ {
	 681  							w.Write(line)
	 682  						}
	 683  						w.Flush()
	 684  					}
	 685  				})
	 686  			})
	 687  		}
	 688  	}
	 689  }
	 690  
	 691  func BenchmarkPyramid(b *testing.B) {
	 692  	for _, x := range [...]int{10, 100, 1000} {
	 693  		// Build a line with x cells.
	 694  		line := bytes.Repeat([]byte("a\t"), x)
	 695  		b.Run(fmt.Sprintf("%d", x), func(b *testing.B) {
	 696  			b.ReportAllocs()
	 697  			for i := 0; i < b.N; i++ {
	 698  				w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
	 699  				// Write increasing prefixes of that line.
	 700  				for j := 0; j < x; j++ {
	 701  					w.Write(line[:j*2])
	 702  					w.Write([]byte{'\n'})
	 703  				}
	 704  				w.Flush()
	 705  			}
	 706  		})
	 707  	}
	 708  }
	 709  
	 710  func BenchmarkRagged(b *testing.B) {
	 711  	var lines [8][]byte
	 712  	for i, w := range [8]int{6, 2, 9, 5, 5, 7, 3, 8} {
	 713  		// Build a line with w cells.
	 714  		lines[i] = bytes.Repeat([]byte("a\t"), w)
	 715  	}
	 716  	for _, h := range [...]int{10, 100, 1000} {
	 717  		b.Run(fmt.Sprintf("%d", h), func(b *testing.B) {
	 718  			b.ReportAllocs()
	 719  			for i := 0; i < b.N; i++ {
	 720  				w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
	 721  				// Write the lines in turn h times.
	 722  				for j := 0; j < h; j++ {
	 723  					w.Write(lines[j%len(lines)])
	 724  					w.Write([]byte{'\n'})
	 725  				}
	 726  				w.Flush()
	 727  			}
	 728  		})
	 729  	}
	 730  }
	 731  
	 732  const codeSnippet = `
	 733  some command
	 734  
	 735  foo	# aligned
	 736  barbaz	# comments
	 737  
	 738  but
	 739  mostly
	 740  single
	 741  cell
	 742  lines
	 743  `
	 744  
	 745  func BenchmarkCode(b *testing.B) {
	 746  	b.ReportAllocs()
	 747  	for i := 0; i < b.N; i++ {
	 748  		w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
	 749  		// The code is small, so it's reasonable for the tabwriter user
	 750  		// to write it all at once, or buffer the writes.
	 751  		w.Write([]byte(codeSnippet))
	 752  		w.Flush()
	 753  	}
	 754  }
	 755  

View as plain text