#include #include #include #include #include #include #include #include #include #include #include #define bt_ioremap(b,l) ((u8 *)__acpi_map_table(b,l)) #define bt_iounmap(b,l) ((void)0) #define memcpy_fromio memcpy #define alloc_bootmem(l) xmalloc_bytes(l) struct dmi_header { u8 type; u8 length; u16 handle; }; #undef DMI_DEBUG #ifdef DMI_DEBUG #define dmi_printk(x) printk x #else #define dmi_printk(x) #endif static char * __init dmi_string(struct dmi_header *dm, u8 s) { char *bp=(char *)dm; bp+=dm->length; if(!s) return ""; s--; while(s>0 && *bp) { bp+=strlen(bp); bp++; s--; } return bp; } /* * We have to be cautious here. We have seen BIOSes with DMI pointers * pointing to completely the wrong place for example */ static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *)) { u8 *buf; struct dmi_header *dm; u8 *data; int i=0; buf = bt_ioremap(base, len); if(buf==NULL) return -1; data = buf; /* * Stop when we see all the items the table claimed to have * OR we run off the end of the table (also happens) */ while(ilength; while(data-buf>4, buf[14]&0x0F); else printk(KERN_INFO "DMI present.\n"); dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n", num, len)); dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base)); if(dmi_table(base,len, num, decode)==0) return 0; } } return -1; } static char *dmi_ident[DMI_STRING_MAX]; /* * Save a DMI string */ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) { char *d = (char*)dm; char *p = dmi_string(dm, d[string]); if(p==NULL || *p == 0) return; if (dmi_ident[slot]) return; dmi_ident[slot] = alloc_bootmem(strlen(p)+1); if(dmi_ident[slot]) strlcpy(dmi_ident[slot], p, strlen(p)+1); else printk(KERN_ERR "dmi_save_ident: out of memory.\n"); } /* * Ugly compatibility crap. */ #define dmi_blacklist dmi_system_id #define NO_MATCH { DMI_NONE, NULL} #define MATCH DMI_MATCH /* * Toshiba keyboard likes to repeat keys when they are not repeated. */ static __init int broken_toshiba_keyboard(struct dmi_blacklist *d) { printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, see http://davyd.ucc.asn.au/projects/toshiba/README\n"); return 0; } #ifdef CONFIG_ACPI_SLEEP static __init int reset_videomode_after_s3(struct dmi_blacklist *d) { /* See acpi_wakeup.S */ acpi_video_flags |= 2; return 0; } #endif #ifdef CONFIG_ACPI_BOOT extern int acpi_force; static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d) { if (!acpi_force) { printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); disable_acpi(); } else { printk(KERN_NOTICE "Warning: DMI blacklist says broken, but acpi forced\n"); } return 0; } /* * Limit ACPI to CPU enumeration for HT */ static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) { if (!acpi_force) { printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); disable_acpi(); acpi_ht = 1; } else { printk(KERN_NOTICE "Warning: acpi=force overrules DMI blacklist: acpi=ht\n"); } return 0; } #endif #ifdef CONFIG_ACPI_PCI static __init int disable_acpi_irq(struct dmi_blacklist *d) { if (!acpi_force) { printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", d->ident); acpi_noirq_set(); } return 0; } static __init int disable_acpi_pci(struct dmi_blacklist *d) { if (!acpi_force) { printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident); acpi_disable_pci(); } return 0; } #endif /* * Process the DMI blacklists */ /* * This will be expanded over time to force things like the APM * interrupt mask settings according to the laptop */ static __initdata struct dmi_blacklist dmi_blacklist[]={ { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */ MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), NO_MATCH, NO_MATCH, NO_MATCH } }, #ifdef CONFIG_ACPI_SLEEP { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */ MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), NO_MATCH, NO_MATCH, NO_MATCH } }, #endif #ifdef CONFIG_ACPI_BOOT /* * If your system is blacklisted here, but you find that acpi=force * works for you, please contact acpi-devel@sourceforge.net */ /* * Boxes that need ACPI disabled */ { dmi_disable_acpi, "IBM Thinkpad", { MATCH(DMI_BOARD_VENDOR, "IBM"), MATCH(DMI_BOARD_NAME, "2629H1G"), NO_MATCH, NO_MATCH }}, /* * Boxes that need acpi=ht */ { force_acpi_ht, "FSC Primergy T850", { MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "DELL GX240", { MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"), MATCH(DMI_BOARD_NAME, "OptiPlex GX240"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "HP VISUALIZE NT Workstation", { MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "Compaq Workstation W8000", { MATCH(DMI_SYS_VENDOR, "Compaq"), MATCH(DMI_PRODUCT_NAME, "Workstation W8000"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "ASUS P4B266", { MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), MATCH(DMI_BOARD_NAME, "P4B266"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "ASUS P2B-DS", { MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), MATCH(DMI_BOARD_NAME, "P2B-DS"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "ASUS CUR-DLS", { MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), MATCH(DMI_BOARD_NAME, "CUR-DLS"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "ABIT i440BX-W83977", { MATCH(DMI_BOARD_VENDOR, "ABIT "), MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "IBM Bladecenter", { MATCH(DMI_BOARD_VENDOR, "IBM"), MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "IBM eServer xSeries 360", { MATCH(DMI_BOARD_VENDOR, "IBM"), MATCH(DMI_BOARD_NAME, "eServer xSeries 360"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "IBM eserver xSeries 330", { MATCH(DMI_BOARD_VENDOR, "IBM"), MATCH(DMI_BOARD_NAME, "eserver xSeries 330"), NO_MATCH, NO_MATCH }}, { force_acpi_ht, "IBM eserver xSeries 440", { MATCH(DMI_BOARD_VENDOR, "IBM"), MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"), NO_MATCH, NO_MATCH }}, #endif // CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_PCI /* * Boxes that need ACPI PCI IRQ routing disabled */ { disable_acpi_irq, "ASUS A7V", { MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), MATCH(DMI_BOARD_NAME, ""), /* newer BIOS, Revision 1011, does work */ MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), NO_MATCH }}, /* * Boxes that need ACPI PCI IRQ routing and PCI scan disabled */ { disable_acpi_pci, "ASUS PR-DLS", { /* _BBN 0 bug */ MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), MATCH(DMI_BOARD_NAME, "PR-DLS"), MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"), MATCH(DMI_BIOS_DATE, "03/21/2003") }}, { disable_acpi_pci, "Acer TravelMate 36x Laptop", { MATCH(DMI_SYS_VENDOR, "Acer"), MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), NO_MATCH, NO_MATCH } }, #endif { NULL, } }; /* * Process a DMI table entry. Right now all we care about are the BIOS * and machine entries. For 2.5 we should pull the smbus controller info * out of here. */ static void __init dmi_decode(struct dmi_header *dm) { #ifdef DMI_DEBUG u8 *data = (u8 *)dm; #endif switch(dm->type) { case 0: dmi_printk(("BIOS Vendor: %s\n", dmi_string(dm, data[4]))); dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); dmi_printk(("BIOS Version: %s\n", dmi_string(dm, data[5]))); dmi_save_ident(dm, DMI_BIOS_VERSION, 5); dmi_printk(("BIOS Release: %s\n", dmi_string(dm, data[8]))); dmi_save_ident(dm, DMI_BIOS_DATE, 8); break; case 1: dmi_printk(("System Vendor: %s\n", dmi_string(dm, data[4]))); dmi_save_ident(dm, DMI_SYS_VENDOR, 4); dmi_printk(("Product Name: %s\n", dmi_string(dm, data[5]))); dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); dmi_printk(("Version: %s\n", dmi_string(dm, data[6]))); dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); dmi_printk(("Serial Number: %s\n", dmi_string(dm, data[7]))); break; case 2: dmi_printk(("Board Vendor: %s\n", dmi_string(dm, data[4]))); dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); dmi_printk(("Board Name: %s\n", dmi_string(dm, data[5]))); dmi_save_ident(dm, DMI_BOARD_NAME, 5); dmi_printk(("Board Version: %s\n", dmi_string(dm, data[6]))); dmi_save_ident(dm, DMI_BOARD_VERSION, 6); break; } } void __init dmi_scan_machine(void) { int err = dmi_iterate(dmi_decode); if(err == 0) dmi_check_system(dmi_blacklist); else printk(KERN_INFO "DMI not present.\n"); } /** * dmi_check_system - check system DMI data * @list: array of dmi_system_id structures to match against * * Walk the blacklist table running matching functions until someone * returns non zero or we hit the end. Callback function is called for * each successfull match. Returns the number of matches. */ int dmi_check_system(struct dmi_system_id *list) { int i, count = 0; struct dmi_system_id *d = list; while (d->ident) { for (i = 0; i < ARRAY_SIZE(d->matches); i++) { int s = d->matches[i].slot; if (s == DMI_NONE) continue; if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr)) continue; /* No match */ goto fail; } if (d->callback && d->callback(d)) break; count++; fail: d++; } return count; } EXPORT_SYMBOL(dmi_check_system); /** * dmi_get_system_info - return DMI data value * @field: data index (see enum dmi_filed) * * Returns one DMI data value, can be used to perform * complex DMI data checks. */ char * dmi_get_system_info(int field) { return dmi_ident[field]; } EXPORT_SYMBOL(dmi_get_system_info); ='#n247'>247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 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
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)

// Google Mock - a framework for writing C++ mock classes.
//
// This file tests the built-in actions in gmock-more-actions.h.

#include "gmock/gmock-more-actions.h"

#include <functional>
#include <sstream>
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "gtest/internal/gtest-linked_ptr.h"

namespace testing {
namespace gmock_more_actions_test {

using ::std::plus;
using ::std::string;
using testing::get;
using testing::make_tuple;
using testing::tuple;
using testing::tuple_element;
using testing::_;
using testing::Action;
using testing::ActionInterface;
using testing::DeleteArg;
using testing::Invoke;
using testing::Return;
using testing::ReturnArg;
using testing::ReturnPointee;
using testing::SaveArg;
using testing::SaveArgPointee;
using testing::SetArgReferee;
using testing::StaticAssertTypeEq;
using testing::Unused;
using testing::WithArg;
using testing::WithoutArgs;
using testing::internal::linked_ptr;

// For suppressing compiler warnings on conversion possibly losing precision.
inline short Short(short n) { return n; }  // NOLINT
inline char Char(char ch) { return ch; }

// Sample functions and functors for testing Invoke() and etc.
int Nullary() { return 1; }

class NullaryFunctor {
 public:
  int operator()() { return 2; }
};

bool g_done = false;
void VoidNullary() { g_done = true; }

class VoidNullaryFunctor {
 public:
  void operator()() { g_done = true; }
};

bool Unary(int x) { return x < 0; }

const char* Plus1(const char* s) { return s + 1; }

void VoidUnary(int /* n */) { g_done = true; }

bool ByConstRef(const string& s) { return s == "Hi"; }

const double g_double = 0;
bool ReferencesGlobalDouble(const double& x) { return &x == &g_double; }

string ByNonConstRef(string& s) { return s += "+"; }  // NOLINT

struct UnaryFunctor {
  int operator()(bool x) { return x ? 1 : -1; }
};

const char* Binary(const char* input, short n) { return input + n; }  // NOLINT

void VoidBinary(int, char) { g_done = true; }

int Ternary(int x, char y, short z) { return x + y + z; }  // NOLINT

void VoidTernary(int, char, bool) { g_done = true; }

int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }

int SumOfFirst2(int a, int b, Unused, Unused) { return a + b; }

void VoidFunctionWithFourArguments(char, int, float, double) { g_done = true; }

string Concat4(const char* s1, const char* s2, const char* s3,
               const char* s4) {
  return string(s1) + s2 + s3 + s4;
}

int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }

struct SumOf5Functor {
  int operator()(int a, int b, int c, int d, int e) {
    return a + b + c + d + e;
  }
};

string Concat5(const char* s1, const char* s2, const char* s3,
               const char* s4, const char* s5) {
  return string(s1) + s2 + s3 + s4 + s5;
}

int SumOf6(int a, int b, int c, int d, int e, int f) {
  return a + b + c + d + e + f;
}

struct SumOf6Functor {
  int operator()(int a, int b, int c, int d, int e, int f) {
    return a + b + c + d + e + f;
  }
};

string Concat6(const char* s1, const char* s2, const char* s3,
               const char* s4, const char* s5, const char* s6) {
  return string(s1) + s2 + s3 + s4 + s5 + s6;
}

string Concat7(const char* s1, const char* s2, const char* s3,
               const char* s4, const char* s5, const char* s6,
               const char* s7) {
  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
}

string Concat8(const char* s1, const char* s2, const char* s3,
               const char* s4, const char* s5, const char* s6,
               const char* s7, const char* s8) {
  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
}

string Concat9(const char* s1, const char* s2, const char* s3,
               const char* s4, const char* s5, const char* s6,
               const char* s7, const char* s8, const char* s9) {
  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
}

string Concat10(const char* s1, const char* s2, const char* s3,
                const char* s4, const char* s5, const char* s6,
                const char* s7, const char* s8, const char* s9,
                const char* s10) {
  return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
}

class Foo {
 public:
  Foo() : value_(123) {}

  int Nullary() const { return value_; }

  short Unary(long x) { return static_cast<short>(value_ + x); }  // NOLINT

  string Binary(const string& str, char c) const { return str + c; }

  int Ternary(int x, bool y, char z) { return value_ + x + y*z; }

  int SumOf4(int a, int b, int c, int d) const {
    return a + b + c + d + value_;
  }

  int SumOfLast2(Unused, Unused, int a, int b) const { return a + b; }

  int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }

  int SumOf6(int a, int b, int c, int d, int e, int f) {
    return a + b + c + d + e + f;
  }

  string Concat7(const char* s1, const char* s2, const char* s3,
                 const char* s4, const char* s5, const char* s6,
                 const char* s7) {
    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
  }

  string Concat8(const char* s1, const char* s2, const char* s3,
                 const char* s4, const char* s5, const char* s6,
                 const char* s7, const char* s8) {
    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
  }

  string Concat9(const char* s1, const char* s2, const char* s3,
                 const char* s4, const char* s5, const char* s6,
                 const char* s7, const char* s8, const char* s9) {
    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
  }

  string Concat10(const char* s1, const char* s2, const char* s3,
                  const char* s4, const char* s5, const char* s6,
                  const char* s7, const char* s8, const char* s9,
                  const char* s10) {
    return string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
  }

 private:
  int value_;
};

// Tests using Invoke() with a nullary function.
TEST(InvokeTest, Nullary) {
  Action<int()> a = Invoke(Nullary);  // NOLINT
  EXPECT_EQ(1, a.Perform(make_tuple()));
}

// Tests using Invoke() with a unary function.
TEST(InvokeTest, Unary) {
  Action<bool(int)> a = Invoke(Unary);  // NOLINT
  EXPECT_FALSE(a.Perform(make_tuple(1)));
  EXPECT_TRUE(a.Perform(make_tuple(-1)));
}

// Tests using Invoke() with a binary function.
TEST(InvokeTest, Binary) {
  Action<const char*(const char*, short)> a = Invoke(Binary);  // NOLINT
  const char* p = "Hello";
  EXPECT_EQ(p + 2, a.Perform(make_tuple(p, Short(2))));
}

// Tests using Invoke() with a ternary function.
TEST(InvokeTest, Ternary) {
  Action<int(int, char, short)> a = Invoke(Ternary);  // NOLINT
  EXPECT_EQ(6, a.Perform(make_tuple(1, '\2', Short(3))));
}

// Tests using Invoke() with a 4-argument function.
TEST(InvokeTest, FunctionThatTakes4Arguments) {
  Action<int(int, int, int, int)> a = Invoke(SumOf4);  // NOLINT
  EXPECT_EQ(1234, a.Perform(make_tuple(1000, 200, 30, 4)));
}

// Tests using Invoke() with a 5-argument function.
TEST(InvokeTest, FunctionThatTakes5Arguments) {
  Action<int(int, int, int, int, int)> a = Invoke(SumOf5);  // NOLINT
  EXPECT_EQ(12345, a.Perform(make_tuple(10000, 2000, 300, 40, 5)));
}

// Tests using Invoke() with a 6-argument function.
TEST(InvokeTest, FunctionThatTakes6Arguments) {
  Action<int(int, int, int, int, int, int)> a = Invoke(SumOf6);  // NOLINT
  EXPECT_EQ(123456, a.Perform(make_tuple(100000, 20000, 3000, 400, 50, 6)));
}

// A helper that turns the type of a C-string literal from const
// char[N] to const char*.
inline const char* CharPtr(const char* s) { return s; }

// Tests using Invoke() with a 7-argument function.
TEST(InvokeTest, FunctionThatTakes7Arguments) {
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*)> a =
      Invoke(Concat7);
  EXPECT_EQ("1234567",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"))));
}

// Tests using Invoke() with a 8-argument function.
TEST(InvokeTest, FunctionThatTakes8Arguments) {
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*, const char*)> a =
      Invoke(Concat8);
  EXPECT_EQ("12345678",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"), CharPtr("8"))));
}

// Tests using Invoke() with a 9-argument function.
TEST(InvokeTest, FunctionThatTakes9Arguments) {
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*, const char*,
                const char*)> a = Invoke(Concat9);
  EXPECT_EQ("123456789",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"), CharPtr("8"), CharPtr("9"))));
}

// Tests using Invoke() with a 10-argument function.
TEST(InvokeTest, FunctionThatTakes10Arguments) {
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*, const char*,
                const char*, const char*)> a = Invoke(Concat10);
  EXPECT_EQ("1234567890",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"), CharPtr("8"), CharPtr("9"),
                                 CharPtr("0"))));
}

// Tests using Invoke() with functions with parameters declared as Unused.
TEST(InvokeTest, FunctionWithUnusedParameters) {
  Action<int(int, int, double, const string&)> a1 =
      Invoke(SumOfFirst2);
  string s("hi");
  EXPECT_EQ(12, a1.Perform(
    tuple<int, int, double, const string&>(10, 2, 5.6, s)));

  Action<int(int, int, bool, int*)> a2 =
      Invoke(SumOfFirst2);
  EXPECT_EQ(23, a2.Perform(make_tuple(20, 3, true, static_cast<int*>(NULL))));
}

// Tests using Invoke() with methods with parameters declared as Unused.
TEST(InvokeTest, MethodWithUnusedParameters) {
  Foo foo;
  Action<int(string, bool, int, int)> a1 =
      Invoke(&foo, &Foo::SumOfLast2);
  EXPECT_EQ(12, a1.Perform(make_tuple(CharPtr("hi"), true, 10, 2)));

  Action<int(char, double, int, int)> a2 =
      Invoke(&foo, &Foo::SumOfLast2);
  EXPECT_EQ(23, a2.Perform(make_tuple('a', 2.5, 20, 3)));
}

// Tests using Invoke() with a functor.
TEST(InvokeTest, Functor) {
  Action<long(long, int)> a = Invoke(plus<long>());  // NOLINT
  EXPECT_EQ(3L, a.Perform(make_tuple(1, 2)));
}

// Tests using Invoke(f) as an action of a compatible type.
TEST(InvokeTest, FunctionWithCompatibleType) {
  Action<long(int, short, char, bool)> a = Invoke(SumOf4);  // NOLINT
  EXPECT_EQ(4321, a.Perform(make_tuple(4000, Short(300), Char(20), true)));
}

// Tests using Invoke() with an object pointer and a method pointer.

// Tests using Invoke() with a nullary method.
TEST(InvokeMethodTest, Nullary) {
  Foo foo;
  Action<int()> a = Invoke(&foo, &Foo::Nullary);  // NOLINT
  EXPECT_EQ(123, a.Perform(make_tuple()));
}

// Tests using Invoke() with a unary method.
TEST(InvokeMethodTest, Unary) {
  Foo foo;
  Action<short(long)> a = Invoke(&foo, &Foo::Unary);  // NOLINT
  EXPECT_EQ(4123, a.Perform(make_tuple(4000)));
}

// Tests using Invoke() with a binary method.
TEST(InvokeMethodTest, Binary) {
  Foo foo;
  Action<string(const string&, char)> a = Invoke(&foo, &Foo::Binary);
  string s("Hell");
  EXPECT_EQ("Hello", a.Perform(
      tuple<const string&, char>(s, 'o')));
}

// Tests using Invoke() with a ternary method.
TEST(InvokeMethodTest, Ternary) {
  Foo foo;
  Action<int(int, bool, char)> a = Invoke(&foo, &Foo::Ternary);  // NOLINT
  EXPECT_EQ(1124, a.Perform(make_tuple(1000, true, Char(1))));
}

// Tests using Invoke() with a 4-argument method.
TEST(InvokeMethodTest, MethodThatTakes4Arguments) {
  Foo foo;
  Action<int(int, int, int, int)> a = Invoke(&foo, &Foo::SumOf4);  // NOLINT
  EXPECT_EQ(1357, a.Perform(make_tuple(1000, 200, 30, 4)));
}

// Tests using Invoke() with a 5-argument method.
TEST(InvokeMethodTest, MethodThatTakes5Arguments) {
  Foo foo;
  Action<int(int, int, int, int, int)> a = Invoke(&foo, &Foo::SumOf5);  // NOLINT
  EXPECT_EQ(12345, a.Perform(make_tuple(10000, 2000, 300, 40, 5)));
}

// Tests using Invoke() with a 6-argument method.
TEST(InvokeMethodTest, MethodThatTakes6Arguments) {
  Foo foo;
  Action<int(int, int, int, int, int, int)> a =  // NOLINT
      Invoke(&foo, &Foo::SumOf6);
  EXPECT_EQ(123456, a.Perform(make_tuple(100000, 20000, 3000, 400, 50, 6)));
}

// Tests using Invoke() with a 7-argument method.
TEST(InvokeMethodTest, MethodThatTakes7Arguments) {
  Foo foo;
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*)> a =
      Invoke(&foo, &Foo::Concat7);
  EXPECT_EQ("1234567",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"))));
}

// Tests using Invoke() with a 8-argument method.
TEST(InvokeMethodTest, MethodThatTakes8Arguments) {
  Foo foo;
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*, const char*)> a =
      Invoke(&foo, &Foo::Concat8);
  EXPECT_EQ("12345678",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"), CharPtr("8"))));
}

// Tests using Invoke() with a 9-argument method.
TEST(InvokeMethodTest, MethodThatTakes9Arguments) {
  Foo foo;
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*, const char*,
                const char*)> a = Invoke(&foo, &Foo::Concat9);
  EXPECT_EQ("123456789",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"), CharPtr("8"), CharPtr("9"))));
}

// Tests using Invoke() with a 10-argument method.
TEST(InvokeMethodTest, MethodThatTakes10Arguments) {
  Foo foo;
  Action<string(const char*, const char*, const char*, const char*,
                const char*, const char*, const char*, const char*,
                const char*, const char*)> a = Invoke(&foo, &Foo::Concat10);
  EXPECT_EQ("1234567890",
            a.Perform(make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
                                 CharPtr("4"), CharPtr("5"), CharPtr("6"),
                                 CharPtr("7"), CharPtr("8"), CharPtr("9"),
                                 CharPtr("0"))));
}

// Tests using Invoke(f) as an action of a compatible type.
TEST(InvokeMethodTest, MethodWithCompatibleType) {
  Foo foo;
  Action<long(int, short, char, bool)> a =  // NOLINT
      Invoke(&foo, &Foo::SumOf4);
  EXPECT_EQ(4444, a.Perform(make_tuple(4000, Short(300), Char(20), true)));
}

// Tests using WithoutArgs with an action that takes no argument.
TEST(WithoutArgsTest, NoArg) {
  Action<int(int n)> a = WithoutArgs(Invoke(Nullary));  // NOLINT
  EXPECT_EQ(1, a.Perform(make_tuple(2)));
}

// Tests using WithArg with an action that takes 1 argument.
TEST(WithArgTest, OneArg) {
  Action<bool(double x, int n)> b = WithArg<1>(Invoke(Unary));  // NOLINT
  EXPECT_TRUE(b.Perform(make_tuple(1.5, -1)));
  EXPECT_FALSE(b.Perform(make_tuple(1.5, 1)));
}

TEST(ReturnArgActionTest, WorksForOneArgIntArg0) {
  const Action<int(int)> a = ReturnArg<0>();
  EXPECT_EQ(5, a.Perform(make_tuple(5)));
}

TEST(ReturnArgActionTest, WorksForMultiArgBoolArg0) {
  const Action<bool(bool, bool, bool)> a = ReturnArg<0>();
  EXPECT_TRUE(a.Perform(make_tuple(true, false, false)));
}

TEST(ReturnArgActionTest, WorksForMultiArgStringArg2) {
  const Action<string(int, int, string, int)> a = ReturnArg<2>();
  EXPECT_EQ("seven", a.Perform(make_tuple(5, 6, string("seven"), 8)));
}

TEST(SaveArgActionTest, WorksForSameType) {
  int result = 0;
  const Action<void(int n)> a1 = SaveArg<0>(&result);
  a1.Perform(make_tuple(5));
  EXPECT_EQ(5, result);
}

TEST(SaveArgActionTest, WorksForCompatibleType) {
  int result = 0;
  const Action<void(bool, char)> a1 = SaveArg<1>(&result);
  a1.Perform(make_tuple(true, 'a'));
  EXPECT_EQ('a', result);
}

TEST(SaveArgPointeeActionTest, WorksForSameType) {
  int result = 0;
  const int value = 5;
  const Action<void(const int*)> a1 = SaveArgPointee<0>(&result);
  a1.Perform(make_tuple(&value));
  EXPECT_EQ(5, result);
}

TEST(SaveArgPointeeActionTest, WorksForCompatibleType) {
  int result = 0;
  char value = 'a';
  const Action<void(bool, char*)> a1 = SaveArgPointee<1>(&result);
  a1.Perform(make_tuple(true, &value));
  EXPECT_EQ('a', result);
}

TEST(SaveArgPointeeActionTest, WorksForLinkedPtr) {
  int result = 0;
  linked_ptr<int> value(new int(5));
  const Action<void(linked_ptr<int>)> a1 = SaveArgPointee<0>(&result);
  a1.Perform(make_tuple(value));
  EXPECT_EQ(5, result);
}

TEST(SetArgRefereeActionTest, WorksForSameType) {
  int value = 0;
  const Action<void(int&)> a1 = SetArgReferee<0>(1);
  a1.Perform(tuple<int&>(value));
  EXPECT_EQ(1, value);
}

TEST(SetArgRefereeActionTest, WorksForCompatibleType) {
  int value = 0;
  const Action<void(int, int&)> a1 = SetArgReferee<1>('a');
  a1.Perform(tuple<int, int&>(0, value));
  EXPECT_EQ('a', value);
}

TEST(SetArgRefereeActionTest, WorksWithExtraArguments) {
  int value = 0;
  const Action<void(bool, int, int&, const char*)> a1 = SetArgReferee<2>('a');
  a1.Perform(tuple<bool, int, int&, const char*>(true, 0, value, "hi"));
  EXPECT_EQ('a', value);
}

// A class that can be used to verify that its destructor is called: it will set
// the bool provided to the constructor to true when destroyed.
class DeletionTester {
 public:
  explicit DeletionTester(bool* is_deleted)
    : is_deleted_(is_deleted) {
    // Make sure the bit is set to false.
    *is_deleted_ = false;
  }

  ~DeletionTester() {
    *is_deleted_ = true;
  }

 private:
  bool* is_deleted_;
};

TEST(DeleteArgActionTest, OneArg) {
  bool is_deleted = false;
  DeletionTester* t = new DeletionTester(&is_deleted);
  const Action<void(DeletionTester*)> a1 = DeleteArg<0>();      // NOLINT
  EXPECT_FALSE(is_deleted);
  a1.Perform(make_tuple(t));
  EXPECT_TRUE(is_deleted);
}

TEST(DeleteArgActionTest, TenArgs) {
  bool is_deleted = false;
  DeletionTester* t = new DeletionTester(&is_deleted);
  const Action<void(bool, int, int, const char*, bool,
                    int, int, int, int, DeletionTester*)> a1 = DeleteArg<9>();
  EXPECT_FALSE(is_deleted);
  a1.Perform(make_tuple(true, 5, 6, CharPtr("hi"), false, 7, 8, 9, 10, t));
  EXPECT_TRUE(is_deleted);
}

#if GTEST_HAS_EXCEPTIONS

TEST(ThrowActionTest, ThrowsGivenExceptionInVoidFunction) {
  const Action<void(int n)> a = Throw('a');
  EXPECT_THROW(a.Perform(make_tuple(0)), char);
}

class MyException {};

TEST(ThrowActionTest, ThrowsGivenExceptionInNonVoidFunction) {
  const Action<double(char ch)> a = Throw(MyException());
  EXPECT_THROW(a.Perform(make_tuple('0')), MyException);
}

TEST(ThrowActionTest, ThrowsGivenExceptionInNullaryFunction) {
  const Action<double()> a = Throw(MyException());
  EXPECT_THROW(a.Perform(make_tuple()), MyException);
}

#endif  // GTEST_HAS_EXCEPTIONS

// Tests that SetArrayArgument<N>(first, last) sets the elements of the array
// pointed to by the N-th (0-based) argument to values in range [first, last).
TEST(SetArrayArgumentTest, SetsTheNthArray) {
  typedef void MyFunction(bool, int*, char*);
  int numbers[] = { 1, 2, 3 };
  Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers + 3);

  int n[4] = {};
  int* pn = n;
  char ch[4] = {};
  char* pch = ch;
  a.Perform(make_tuple(true, pn, pch));
  EXPECT_EQ(1, n[0]);
  EXPECT_EQ(2, n[1]);
  EXPECT_EQ(3, n[2]);
  EXPECT_EQ(0, n[3]);
  EXPECT_EQ('\0', ch[0]);
  EXPECT_EQ('\0', ch[1]);
  EXPECT_EQ('\0', ch[2]);
  EXPECT_EQ('\0', ch[3]);

  // Tests first and last are iterators.
  std::string letters = "abc";
  a = SetArrayArgument<2>(letters.begin(), letters.end());
  std::fill_n(n, 4, 0);
  std::fill_n(ch, 4, '\0');
  a.Perform(make_tuple(true, pn, pch));
  EXPECT_EQ(0, n[0]);
  EXPECT_EQ(0, n[1]);
  EXPECT_EQ(0, n[2]);
  EXPECT_EQ(0, n[3]);
  EXPECT_EQ('a', ch[0]);
  EXPECT_EQ('b', ch[1]);
  EXPECT_EQ('c', ch[2]);
  EXPECT_EQ('\0', ch[3]);
}

// Tests SetArrayArgument<N>(first, last) where first == last.
TEST(SetArrayArgumentTest, SetsTheNthArrayWithEmptyRange) {
  typedef void MyFunction(bool, int*);
  int numbers[] = { 1, 2, 3 };
  Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers);

  int n[4] = {};
  int* pn = n;
  a.Perform(make_tuple(true, pn));
  EXPECT_EQ(0, n[0]);
  EXPECT_EQ(0, n[1]);
  EXPECT_EQ(0, n[2]);
  EXPECT_EQ(0, n[3]);
}

// Tests SetArrayArgument<N>(first, last) where *first is convertible
// (but not equal) to the argument type.
TEST(SetArrayArgumentTest, SetsTheNthArrayWithConvertibleType) {
  typedef void MyFunction(bool, int*);
  char chars[] = { 97, 98, 99 };
  Action<MyFunction> a = SetArrayArgument<1>(chars, chars + 3);

  int codes[4] = { 111, 222, 333, 444 };
  int* pcodes = codes;
  a.Perform(make_tuple(true, pcodes));
  EXPECT_EQ(97, codes[0]);
  EXPECT_EQ(98, codes[1]);
  EXPECT_EQ(99, codes[2]);
  EXPECT_EQ(444, codes[3]);
}

// Test SetArrayArgument<N>(first, last) with iterator as argument.
TEST(SetArrayArgumentTest, SetsTheNthArrayWithIteratorArgument) {
  typedef void MyFunction(bool, std::back_insert_iterator<std::string>);
  std::string letters = "abc";
  Action<MyFunction> a = SetArrayArgument<1>(letters.begin(), letters.end());

  std::string s;
  a.Perform(make_tuple(true, back_inserter(s)));
  EXPECT_EQ(letters, s);
}

TEST(ReturnPointeeTest, Works) {
  int n = 42;
  const Action<int()> a = ReturnPointee(&n);
  EXPECT_EQ(42, a.Perform(make_tuple()));

  n = 43;
  EXPECT_EQ(43, a.Perform(make_tuple()));
}

}  // namespace gmock_generated_actions_test
}  // namespace testing