<commit_before>/*
  c2ffi
  Copyright (C) 2013  Ryan Pavlik

  This file is part of c2ffi.

  c2ffi is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 2 of the License, or
  (at your option) any later version.

  c2ffi is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with c2ffi.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>

#include <llvm/Support/Host.h>
#include <llvm/ADT/IntrusiveRefCntPtr.h>

#include <clang/Basic/DiagnosticOptions.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/FrontendTool/Utils.h>
#include <clang/Basic/TargetOptions.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/Parse/Parser.h>
#include <clang/Parse/ParseAST.h>

#include <sys/stat.h>

#include "c2ffi/init.h"

using namespace c2ffi;

void c2ffi::add_include(clang::CompilerInstance &ci, const char *path, bool is_angled,
                        bool show_error) {
    struct stat buf;
    if(stat(path, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
        if(show_error) {
            std::cerr << "Error: Not a directory: ";
            if(is_angled)
                std::cerr << "-i ";
            else
                std::cerr << "-I ";

            std::cerr << path << std::endl;
            exit(1);
        }

        return;
    }

    const clang::DirectoryEntry *dirent = ci.getFileManager().getDirectory(path);
    clang::DirectoryLookup lookup(dirent, clang::SrcMgr::C_System, false);

    ci.getPreprocessor().getHeaderSearchInfo()
        .AddSearchPath(lookup, is_angled);
}

void c2ffi::add_includes(clang::CompilerInstance &ci,
                         c2ffi::IncludeVector &v, bool is_angled,
                         bool show_error) {
    for(c2ffi::IncludeVector::iterator i = v.begin(); i != v.end(); i++)
        add_include(ci, (*i).c_str(), is_angled, show_error);
}

void c2ffi::init_ci(config &c, clang::CompilerInstance &ci) {
    using clang::DiagnosticOptions;
    using clang::TextDiagnosticPrinter;
    using clang::TargetOptions;
    using clang::TargetInfo;

    ci.getInvocation().setLangDefaults(ci.getLangOpts(), c.kind,
                                       clang::LangStandard::lang_unspecified);

    DiagnosticOptions *dopt = new DiagnosticOptions;
    TextDiagnosticPrinter *tpd =
        new TextDiagnosticPrinter(llvm::errs(), dopt, true);
    ci.createDiagnostics(tpd);

    llvm::IntrusiveRefCntPtr<TargetOptions> *pto =
        new llvm::IntrusiveRefCntPtr<TargetOptions>(new TargetOptions());
    (*pto)->Triple = llvm::sys::getDefaultTargetTriple();
    TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto->getPtr());
    ci.setTarget(pti);

    ci.createFileManager();
    ci.createSourceManager(ci.getFileManager());
    ci.createPreprocessor();
    ci.getPreprocessorOpts().UsePredefines = false;
}

<commit_msg>Prevent double-free (fixed vs clang@181334)<commit_after>/*
  c2ffi
  Copyright (C) 2013  Ryan Pavlik

  This file is part of c2ffi.

  c2ffi is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 2 of the License, or
  (at your option) any later version.

  c2ffi is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with c2ffi.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>

#include <llvm/Support/Host.h>
#include <llvm/ADT/IntrusiveRefCntPtr.h>

#include <clang/Basic/DiagnosticOptions.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/FrontendTool/Utils.h>
#include <clang/Basic/TargetOptions.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/Parse/Parser.h>
#include <clang/Parse/ParseAST.h>

#include <sys/stat.h>

#include "c2ffi/init.h"

using namespace c2ffi;

void c2ffi::add_include(clang::CompilerInstance &ci, const char *path, bool is_angled,
                        bool show_error) {
    struct stat buf;
    if(stat(path, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
        if(show_error) {
            std::cerr << "Error: Not a directory: ";
            if(is_angled)
                std::cerr << "-i ";
            else
                std::cerr << "-I ";

            std::cerr << path << std::endl;
            exit(1);
        }

        return;
    }

    const clang::DirectoryEntry *dirent = ci.getFileManager().getDirectory(path);
    clang::DirectoryLookup lookup(dirent, clang::SrcMgr::C_System, false);

    ci.getPreprocessor().getHeaderSearchInfo()
        .AddSearchPath(lookup, is_angled);
}

void c2ffi::add_includes(clang::CompilerInstance &ci,
                         c2ffi::IncludeVector &v, bool is_angled,
                         bool show_error) {
    for(c2ffi::IncludeVector::iterator i = v.begin(); i != v.end(); i++)
        add_include(ci, (*i).c_str(), is_angled, show_error);
}

void c2ffi::init_ci(config &c, clang::CompilerInstance &ci) {
    using clang::DiagnosticOptions;
    using clang::TextDiagnosticPrinter;
    using clang::TargetOptions;
    using clang::TargetInfo;

    ci.getInvocation().setLangDefaults(ci.getLangOpts(), c.kind,
                                       clang::LangStandard::lang_unspecified);

    DiagnosticOptions *dopt = new DiagnosticOptions;
    TextDiagnosticPrinter *tpd =
        new TextDiagnosticPrinter(llvm::errs(), dopt, false);
    ci.createDiagnostics(tpd);

    llvm::IntrusiveRefCntPtr<TargetOptions> *pto =
        new llvm::IntrusiveRefCntPtr<TargetOptions>(new TargetOptions());
    (*pto)->Triple = llvm::sys::getDefaultTargetTriple();
    TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto->getPtr());
    ci.setTarget(pti);

    ci.createFileManager();
    ci.createSourceManager(ci.getFileManager());
    ci.createPreprocessor();
    ci.getPreprocessorOpts().UsePredefines = false;
}

<|endoftext|>


<commit_before>/*Se considera fisierul BAC.TXT ce contine un sir crescator cu cel mult un milion
de numere naturale de cel mult noua cifre fiecare, separate prin câte un spatiu.
Sa se scrie un program C/C++ care, folosind un algoritm eficient din punct de vedere
al memoriei utilizate si al timpului de executare, citeste din fisier toti termenii
sirului si afiseaza pe ecran, pe o singura linie, fiecare termen distinct al sirului
urmat de numarul de aparitii ale acestuia în sir. Valorile afisate sunt separate prin
câte un spatiu. Exemplu: daca fisierul BAC.TXT are urmatorul continut:
1 1 1 5 5 5 5 9 9 11 20 20 20 programul va afisa: 1 3 5 4 9 2 11 1 20 3
deoarece 1 apare de 3 ori, 5 apare de 4 ori,etc
*/

#include <fstream>

using namespace std;

int main()
{
    ifstream f("BAC.TXT");

    long x, y, n;
    f >> x;
    n = 1;

    while(f >> y)
    {
        if(x == y)
        {
            n++;
        }
        else
        {
            cout << x << " " << n << " ";
	        n = 1;
	    }
    x = y;
    }

    cout << x << " " << n;
    return 0;
}
<commit_msg>Update Problema1.cpp<commit_after>/*Se considera fisierul BAC.TXT ce contine un sir crescator cu cel mult un milion
de numere naturale de cel mult noua cifre fiecare, separate prin câte un spatiu.
Sa se scrie un program C/C++ care, folosind un algoritm eficient din punct de vedere
al memoriei utilizate si al timpului de executare, citeste din fisier toti termenii
sirului si afiseaza pe ecran, pe o singura linie, fiecare termen distinct al sirului
urmat de numarul de aparitii ale acestuia în sir. Valorile afisate sunt separate prin
câte un spatiu. Exemplu: daca fisierul BAC.TXT are urmatorul continut:
1 1 1 5 5 5 5 9 9 11 20 20 20 programul va afisa: 1 3 5 4 9 2 11 1 20 3
deoarece 1 apare de 3 ori, 5 apare de 4 ori,etc
*/

#include <fstream>

using namespace std;

int main()
{
    ifstream f("input.in");

    long x, y, n;
    f >> x;
    n = 1;

    while(f >> y)
    {
        if(x == y)
        {
            n++;
        }
        else
        {
            cout << x << " " << n << " ";
	        n = 1;
	    }
    x = y;
    }

    cout << x << " " << n;
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 - 2013 Leap Motion. All rights reserved. Proprietary and confidential.
#include "stdafx.h"
#include "ExceptionFilterTest.h"
#include "EventReceiver.h"
#include "ExceptionFilter.h"
#include <stdexcept>
#include <sstream>
#include <iostream>

using namespace std;

string FormatMessage(int value) {
  std::stringstream sstr;
  sstr << "custom_exception: " << value;
  return sstr.str();
}

class custom_exception:
  public std::exception
{
public:
  custom_exception(int value):
    m_value(value)
  {
  }

  int m_value;
};

/// <summary>
/// Exception type which can track its own destruction
/// </summary>
class tracking_exception:
  public std::exception
{
public:
  tracking_exception(int) {
    s_count++;
  }
  tracking_exception(const tracking_exception& rhs) {
    s_count++;
  }
  ~tracking_exception(void) throw() {
    s_count--;
  }

  static size_t s_count;
};

size_t tracking_exception::s_count = 0;

class ThrowingListener:
  public virtual EventReceiver
{
public:
  ThrowingListener(void) {}
  virtual void DoThrow(void) = 0;
};

template<class Ex>
class ThrowsWhenRun:
  public CoreThread
{
public:
  // This convoluted syntax is required to evade warnings on Mac
  decltype(throw_rethrowable Ex(100)) MakeException() {
    return throw_rethrowable Ex(100);
  }

  void Run(void) override {
    MakeException();
  }
};

template<int i = 200>
class ThrowsWhenFired:
  public ThrowingListener
{
public:
  ThrowsWhenFired(void):
    hit(false)
  {}

  bool hit;

  void DoThrow(void) override {
    hit = true;
    throw_rethrowable custom_exception(i);
  }
};

class GenericFilter:
  public ExceptionFilter
{
public:
  GenericFilter(void):
    m_hit(false),
    m_specific(false),
    m_generic(false),
    m_fireSpecific(false)
  {
  }

  bool m_hit;
  bool m_specific;
  bool m_generic;
  bool m_fireSpecific;

  virtual void Filter(const std::function<void()>& rethrower) override {
    m_hit = true;
    try {
      rethrower();
    } catch(tracking_exception&) {
    } catch(custom_exception& custom) {
      EXPECT_EQ(100, custom.m_value) << "A filtered custom exception did not have the expected member field value";
      m_specific = true;
    } catch(...) {
      m_generic = true;
    }
  }

  virtual void Filter(const std::function<void()>& rethrower, const JunctionBoxBase* pJunctionBox, EventReceiver* pRecipient) override {
    m_hit = true;
    try {
      rethrower();
    } catch(custom_exception& custom) {
      EXPECT_EQ(200, custom.m_value) << "A fired exception did not have the expected value, probable copy malfunction";
      m_fireSpecific = true;
    } catch(...) {
      m_generic = true;
    }
  }
};

TEST_F(ExceptionFilterTest, ExceptionDestruction) {
  // Add the exception filter type to the context first
  AutoRequired<GenericFilter> filter;

  // Now add something that will throw when it's run:
  AutoRequired<ThrowsWhenRun<tracking_exception>> thrower;

  // Run:
  m_create->InitiateCoreThreads();
  thrower->Wait();

  // Verify that the exception was destroyed the correct number of times:
  EXPECT_EQ(0UL, tracking_exception::s_count) << "Exception was not destroyed the correct number of times";
}

TEST_F(ExceptionFilterTest, CheckThrowThrow) {
  class example {
  public:
    example() {
      throw std::exception();
    }
  };

  EXPECT_THROW(throw example(), std::exception) << "An exception type which throws from its ctor did not throw the expected type";
}

TEST_F(ExceptionFilterTest, ThreadThrowsCheck) {
  // Add the exception filter type to the context first
  AutoRequired<GenericFilter> filter;

  // Now add something that will throw when it's run:
  AutoRequired<ThrowsWhenRun<custom_exception>> thrower;

  // Wait for the thrower to terminate, should be pretty fast:
  m_create->InitiateCoreThreads();
  thrower->Wait();

  // Hopefully the filter got hit in the right spot:
  EXPECT_TRUE(filter->m_hit) << "Filter was not invoked for a thrown exception";
  EXPECT_TRUE(filter->m_specific) << "Filter did not correctly detect the exception type";
  EXPECT_FALSE(filter->m_generic) << "Filter did not correctly filter out a specific exception";
}

TEST_F(ExceptionFilterTest, SimpleFilterCheck) {
  // Firing will occur at the parent context scope:
  AutoFired<ThrowingListener> broadcaster;

  // Add the generic filter:
  AutoRequired<GenericFilter> filter;

  // Add a context member which will throw when its event is fired, and a firing class:
  AutoRequired<ThrowsWhenFired<>> fireThrower;

  // Add something to fire the exception:
  EXPECT_NO_THROW(broadcaster(&ThrowingListener::DoThrow)());

  // Verify that the exception was filtered properly by the generic filter:
  EXPECT_TRUE(filter->m_fireSpecific) << "Filter was not invoked on a Fired exception";
}

TEST_F(ExceptionFilterTest, DISABLED_FireContainmentCheck) {
  // Firing will occur at the parent context scope:
  AutoFired<ThrowingListener> broadcaster;

  // Create a subcontext and add the fire thrower to it:
  AutoCreateContext ctxt;
  ctxt->Add<ThrowsWhenFired<>>();

  // Now cause the exception to occur:
  EXPECT_NO_THROW(broadcaster(&ThrowingListener::DoThrow)());

  // Verify that the context containing the fire thrower was torn down:
  EXPECT_TRUE(ctxt->IsShutdown()) << "An unhandled exception from a fire call in a context should have signalled it to stop";

  // Verify that the parent context was protected:
  EXPECT_FALSE(m_create->IsShutdown()) << "An unhandled exception incorrectly terminated a parent context";
}

TEST_F(ExceptionFilterTest, EnclosedThrowCheck) {
  // Create our listener:
  AutoRequired<GenericFilter> filter;

  // Now the subcontext:
  AutoCreateContext subCtxt;
  CurrentContextPusher pshr(subCtxt);

  // Create and start:
  AutoRequired<ThrowsWhenRun<custom_exception>> runThrower;
  subCtxt->InitiateCoreThreads();

  // Wait for the exception to get thrown:
  subCtxt->Wait();

  // Verify that the filter caught the exception:
  EXPECT_TRUE(filter->m_hit) << "Filter operating in a superior context did not catch an exception thrown from a child context";
}

TEST_F(ExceptionFilterTest, VerifyThrowingRecipients) {
  // Create a pair of classes which throw exceptions:
  AutoRequired<ThrowsWhenFired<200>> v200;
  AutoRequired<ThrowsWhenFired<201>> v201;

  // Now try to throw:
  AutoFired<ThrowingListener> tl;
  tl(&ThrowingListener::DoThrow)();

  // Verify that BOTH are hit:
  EXPECT_TRUE(v200->hit && v201->hit) << "Expected all receivers of a fired event will be processed, even if some throw exceptions";
}<commit_msg>Adding a unit test to ensure proper exception isolation<commit_after>// Copyright (c) 2010 - 2013 Leap Motion. All rights reserved. Proprietary and confidential.
#include "stdafx.h"
#include "ExceptionFilterTest.h"
#include "EventReceiver.h"
#include "ExceptionFilter.h"
#include <stdexcept>
#include <sstream>
#include <iostream>

using namespace std;

string FormatMessage(int value) {
  std::stringstream sstr;
  sstr << "custom_exception: " << value;
  return sstr.str();
}

class custom_exception:
  public std::exception
{
public:
  custom_exception(int value):
    m_value(value)
  {
  }

  int m_value;
};

/// <summary>
/// Exception type which can track its own destruction
/// </summary>
class tracking_exception:
  public std::exception
{
public:
  tracking_exception(int) {
    s_count++;
  }
  tracking_exception(const tracking_exception& rhs) {
    s_count++;
  }
  ~tracking_exception(void) throw() {
    s_count--;
  }

  static size_t s_count;
};

size_t tracking_exception::s_count = 0;

class ThrowingListener:
  public virtual EventReceiver
{
public:
  ThrowingListener(void) {}
  virtual void DoThrow(void) = 0;
};

template<class Ex>
class ThrowsWhenRun:
  public CoreThread
{
public:
  // This convoluted syntax is required to evade warnings on Mac
  decltype(throw_rethrowable Ex(100)) MakeException() {
    return throw_rethrowable Ex(100);
  }

  void Run(void) override {
    MakeException();
  }
};

template<int i = 200>
class ThrowsWhenFired:
  public ThrowingListener
{
public:
  ThrowsWhenFired(void):
    hit(false)
  {}

  bool hit;

  void DoThrow(void) override {
    hit = true;
    throw_rethrowable custom_exception(i);
  }
};

class GenericFilter:
  public ExceptionFilter
{
public:
  GenericFilter(void):
    m_hit(false),
    m_specific(false),
    m_generic(false),
    m_fireSpecific(false)
  {
  }

  bool m_hit;
  bool m_specific;
  bool m_generic;
  bool m_fireSpecific;

  virtual void Filter(const std::function<void()>& rethrower) override {
    m_hit = true;
    try {
      rethrower();
    } catch(tracking_exception&) {
    } catch(custom_exception& custom) {
      EXPECT_EQ(100, custom.m_value) << "A filtered custom exception did not have the expected member field value";
      m_specific = true;
    } catch(...) {
      m_generic = true;
    }
  }

  virtual void Filter(const std::function<void()>& rethrower, const JunctionBoxBase* pJunctionBox, EventReceiver* pRecipient) override {
    m_hit = true;
    try {
      rethrower();
    } catch(custom_exception& custom) {
      EXPECT_EQ(200, custom.m_value) << "A fired exception did not have the expected value, probable copy malfunction";
      m_fireSpecific = true;
    } catch(...) {
      m_generic = true;
    }
  }
};

TEST_F(ExceptionFilterTest, ExceptionDestruction) {
  // Add the exception filter type to the context first
  AutoRequired<GenericFilter> filter;

  // Now add something that will throw when it's run:
  AutoRequired<ThrowsWhenRun<tracking_exception>> thrower;

  // Run:
  m_create->InitiateCoreThreads();
  thrower->Wait();

  // Verify that the exception was destroyed the correct number of times:
  EXPECT_EQ(0UL, tracking_exception::s_count) << "Exception was not destroyed the correct number of times";
}

TEST_F(ExceptionFilterTest, CheckThrowThrow) {
  class example {
  public:
    example() {
      throw std::exception();
    }
  };

  EXPECT_THROW(throw example(), std::exception) << "An exception type which throws from its ctor did not throw the expected type";
}

TEST_F(ExceptionFilterTest, ThreadThrowsCheck) {
  // Add the exception filter type to the context first
  AutoRequired<GenericFilter> filter;

  // Now add something that will throw when it's run:
  AutoRequired<ThrowsWhenRun<custom_exception>> thrower;

  // Wait for the thrower to terminate, should be pretty fast:
  m_create->InitiateCoreThreads();
  thrower->Wait();

  // Hopefully the filter got hit in the right spot:
  EXPECT_TRUE(filter->m_hit) << "Filter was not invoked for a thrown exception";
  EXPECT_TRUE(filter->m_specific) << "Filter did not correctly detect the exception type";
  EXPECT_FALSE(filter->m_generic) << "Filter did not correctly filter out a specific exception";
}

TEST_F(ExceptionFilterTest, SimpleFilterCheck) {
  // Firing will occur at the parent context scope:
  AutoFired<ThrowingListener> broadcaster;

  // Add the generic filter:
  AutoRequired<GenericFilter> filter;

  // Add a context member which will throw when its event is fired, and a firing class:
  AutoRequired<ThrowsWhenFired<>> fireThrower;

  // Add something to fire the exception:
  EXPECT_NO_THROW(broadcaster(&ThrowingListener::DoThrow)());

  // Verify that the exception was filtered properly by the generic filter:
  EXPECT_TRUE(filter->m_fireSpecific) << "Filter was not invoked on a Fired exception";
}

TEST_F(ExceptionFilterTest, DISABLED_FireContainmentCheck) {
  // Firing will occur at the parent context scope:
  AutoFired<ThrowingListener> broadcaster;

  // Create a subcontext and add the fire thrower to it:
  AutoCreateContext ctxt;
  ctxt->Add<ThrowsWhenFired<>>();

  // Now cause the exception to occur:
  EXPECT_NO_THROW(broadcaster(&ThrowingListener::DoThrow)());

  // Verify that the context containing the fire thrower was torn down:
  EXPECT_TRUE(ctxt->IsShutdown()) << "An unhandled exception from a fire call in a context should have signalled it to stop";

  // Verify that the parent context was protected:
  EXPECT_FALSE(m_create->IsShutdown()) << "An unhandled exception incorrectly terminated a parent context";
}

TEST_F(ExceptionFilterTest, EnclosedThrowCheck) {
  // Create our listener:
  AutoRequired<GenericFilter> filter;

  // Now the subcontext:
  AutoCreateContext subCtxt;
  CurrentContextPusher pshr(subCtxt);

  // Create and start:
  AutoRequired<ThrowsWhenRun<custom_exception>> runThrower;
  subCtxt->InitiateCoreThreads();

  // Wait for the exception to get thrown:
  subCtxt->Wait();

  // Verify that the filter caught the exception:
  EXPECT_TRUE(filter->m_hit) << "Filter operating in a superior context did not catch an exception thrown from a child context";
}

TEST_F(ExceptionFilterTest, VerifyThrowingRecipients) {
  // Create a pair of classes which throw exceptions:
  AutoRequired<ThrowsWhenFired<200>> v200;
  AutoRequired<ThrowsWhenFired<201>> v201;

  // Now try to throw:
  AutoFired<ThrowingListener> tl;
  tl(&ThrowingListener::DoThrow)();

  // Verify that BOTH are hit:
  EXPECT_TRUE(v200->hit && v201->hit) << "Expected all receivers of a fired event will be processed, even if some throw exceptions";
}

TEST_F(ExceptionFilterTest, VerifySimpleConfinement) {
  m_create->InitiateCoreThreads();

  // Create a subcontext where the errant recipients will live:
  AutoCreateContext child;
  child->Inject<ThrowsWhenFired<200>>();

  // Cause the child context to throw an exception:
  AutoFired<ThrowingListener> tl;
  tl(&ThrowingListener::DoThrow)();

  // Verify that the parent scope wasn't incorrectly terminated:
  EXPECT_FALSE(m_create->IsShutdown()) << "Parent scope was terminated incorrectly due to an exception sourced by a child context";

  // Verify that the child scope was terminated as expected:
  EXPECT_TRUE(child->IsShutdown()) << "An event recipient in a child scope threw an exception and the child context was not correctly terminated";
}<|endoftext|>


<commit_before>/*
 * Copyright 2016 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cartographer/common/configuration_file_resolver.h"

#include <fstream>
#include <iostream>
#include <streambuf>

#include "cartographer/common/config.h"
#include "glog/logging.h"

namespace cartographer {
namespace common {

ConfigurationFileResolver::ConfigurationFileResolver(
    const std::vector<string>& configuration_files_directories)
    : configuration_files_directories_(configuration_files_directories) {
  configuration_files_directories_.push_back(kConfigurationFilesDirectory);
}

string ConfigurationFileResolver::GetFullPathOrDie(const string& basename) {
  for (const auto& path : configuration_files_directories_) {
    const string filename = path + "/" + basename;
    std::ifstream stream(filename.c_str());
    if (stream.good()) {
      return filename;
    }
  }
  LOG(FATAL) << "File " << basename << " was not found.";
}

string ConfigurationFileResolver::GetFileContentOrDie(const string& basename) {
  const string filename = GetFullPathOrDie(basename);
  std::ifstream stream(filename.c_str());
  return string((std::istreambuf_iterator<char>(stream)),
                std::istreambuf_iterator<char>());
}

}  // namespace common
}  // namespace cartographer
<commit_msg>Improved logging for loading Lua configurations. (#4)<commit_after>/*
 * Copyright 2016 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cartographer/common/configuration_file_resolver.h"

#include <fstream>
#include <iostream>
#include <streambuf>

#include "cartographer/common/config.h"
#include "glog/logging.h"

namespace cartographer {
namespace common {

ConfigurationFileResolver::ConfigurationFileResolver(
    const std::vector<string>& configuration_files_directories)
    : configuration_files_directories_(configuration_files_directories) {
  configuration_files_directories_.push_back(kConfigurationFilesDirectory);
}

string ConfigurationFileResolver::GetFullPathOrDie(const string& basename) {
  for (const auto& path : configuration_files_directories_) {
    const string filename = path + "/" + basename;
    std::ifstream stream(filename.c_str());
    if (stream.good()) {
      LOG(INFO) << "Found '" << filename << "' for '" << basename << "'.";
      return filename;
    }
  }
  LOG(FATAL) << "File '" << basename << "' was not found.";
}

string ConfigurationFileResolver::GetFileContentOrDie(const string& basename) {
  const string filename = GetFullPathOrDie(basename);
  std::ifstream stream(filename.c_str());
  return string((std::istreambuf_iterator<char>(stream)),
                std::istreambuf_iterator<char>());
}

}  // namespace common
}  // namespace cartographer
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <GLUT/GLUT.h>

#include "StopWatch.h"

StopWatch stopWatch;
bool started = false;

void Draw(int i) {
	double d;
	glPushMatrix();
	glRotatef(i*6, 0,0,1);
	if(i%5==0) d=2.0;
	else d = 1.0;
	glBegin(GL_TRIANGLES);
	glVertex3f(-0.01*d, 1.0, 0.0);
	glVertex3f( 0.01*d, 1.0, 0.0);
	glVertex3f( 0.0 , 1.0-0.1*d, 0.0);
	glEnd();
	glPopMatrix();
}
void changeSize(int w, int h) {
	if(h == 0) h = 1;
	float ratio = 1.0* w / h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, w, h);
	gluPerspective(45,ratio,1,1000);
	glMatrixMode(GL_MODELVIEW);
}
void renderScene(void) {
	if(!started) {
		stopWatch.start();
		started = true;
	}
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0, 0.0f,1.0f,0.0f);
	for(int i=0; i<60; i++) { Draw(i); }
	glColor3f(0,0,0);

	static float angle;
	stopWatch.stop();
	float dt = stopWatch.getElapsedTime();
	stopWatch.start();
	angle += dt*6.0/1000000.0;

	glPushMatrix();
	glRotatef(-angle, 0.0, 0.0, 1.0);
	glBegin(GL_LINES);
	glVertex3f(0.0,0.0,0.0);
	glVertex3f(0.0,1.0,0.0);
	glEnd();
	glPopMatrix();

	glutSwapBuffers();
}
void processNormalKeys(unsigned char key, int x, int y) {
	if (key == 27) exit(0);
}
int main(int argc, char **argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(320,320);
	glutCreateWindow("Dr.Kang's Animation Lecture - 00");
	glutDisplayFunc(renderScene);
	glutIdleFunc(renderScene);
	glutReshapeFunc(changeSize);
	glutKeyboardFunc(processNormalKeys);
	glEnable(GL_DEPTH_TEST);
	glClearColor(0.8,0.8,1.0,1.0);
	glutMainLoop();
	return 0;
}<commit_msg>add a trivial comment<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <GLUT/GLUT.h>

#include "StopWatch.h"

StopWatch stopWatch;
bool started = false;

void Draw(int i) {
	// drawing clock
	double d;
	glPushMatrix();
	glRotatef(i*6, 0,0,1);
	if(i%5==0) d=2.0;
	else d = 1.0;
	glBegin(GL_TRIANGLES);
	glVertex3f(-0.01*d, 1.0, 0.0);
	glVertex3f( 0.01*d, 1.0, 0.0);
	glVertex3f( 0.0 , 1.0-0.1*d, 0.0);
	glEnd();
	glPopMatrix();
}
void changeSize(int w, int h) {
	if(h == 0) h = 1;
	float ratio = 1.0* w / h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0, 0, w, h);
	gluPerspective(45,ratio,1,1000);
	glMatrixMode(GL_MODELVIEW);
}
void renderScene(void) {
	if(!started) {
		stopWatch.start();
		started = true;
	}
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0, 0.0f,1.0f,0.0f);
	for(int i=0; i<60; i++) { Draw(i); }
	glColor3f(0,0,0);

	static float angle;
	stopWatch.stop();
	float dt = stopWatch.getElapsedTime();
	stopWatch.start();
	angle += dt*6.0/1000000.0;

	glPushMatrix();
	glRotatef(-angle, 0.0, 0.0, 1.0);
	glBegin(GL_LINES);
	glVertex3f(0.0,0.0,0.0);
	glVertex3f(0.0,1.0,0.0);
	glEnd();
	glPopMatrix();

	glutSwapBuffers();
}
void processNormalKeys(unsigned char key, int x, int y) {
	if (key == 27) exit(0);
}
int main(int argc, char **argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(320,320);
	glutCreateWindow("Dr.Kang's Animation Lecture - 00");
	glutDisplayFunc(renderScene);
	glutIdleFunc(renderScene);
	glutReshapeFunc(changeSize);
	glutKeyboardFunc(processNormalKeys);
	glEnable(GL_DEPTH_TEST);
	glClearColor(0.8,0.8,1.0,1.0);
	glutMainLoop();
	return 0;
}<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/ownership_service.h"

#include "base/file_path.h"
#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"

namespace chromeos {

//  static
OwnershipService* OwnershipService::GetSharedInstance() {
  return Singleton<OwnershipService>::get();
}

OwnershipService::OwnershipService()
    : manager_(new OwnerManager),
      utils_(OwnerKeyUtils::Create()) {
}

OwnershipService::~OwnershipService() {}

bool OwnershipService::IsAlreadyOwned() {
  return file_util::PathExists(utils_->GetOwnerKeyFilePath());
}

bool OwnershipService::StartLoadOwnerKeyAttempt() {
  if (!IsAlreadyOwned()) {
    LOG(WARNING) << "Device not yet owned";
    return false;
  }
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(), &OwnerManager::LoadOwnerKey));
  return true;
}

bool OwnershipService::StartTakeOwnershipAttempt() {
  if (IsAlreadyOwned()) {
    LOG(ERROR) << "Device is already owned";
    return false;
  }
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(),
                        &OwnerManager::GenerateKeysAndExportPublic));
  return true;
}

void OwnershipService::StartSigningAttempt(const std::string& data,
                                           OwnerManager::Delegate* d) {
  if (!IsAlreadyOwned()) {
    LOG(ERROR) << "Device not yet owned";
    d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
    return;
  }
  ChromeThread::ID thread_id;
  if (!ChromeThread::GetCurrentThreadIdentifier(&thread_id))
    thread_id = ChromeThread::UI;
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(),
                        &OwnerManager::Sign,
                        thread_id,
                        data, d));
  return;
}

void OwnershipService::StartVerifyAttempt(const std::string& data,
                                          const std::vector<uint8>& signature,
                                          OwnerManager::Delegate* d) {
  if (!IsAlreadyOwned()) {
    LOG(ERROR) << "Device not yet owned";
    d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
    return;
  }
  ChromeThread::ID thread_id;
  if (!ChromeThread::GetCurrentThreadIdentifier(&thread_id))
    thread_id = ChromeThread::UI;
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(),
                        &OwnerManager::Verify,
                        thread_id,
                        data,
                        signature,
                        d));
  return;
}

bool OwnershipService::CurrentUserIsOwner() {
  // If this user has the private key associated with the owner's
  // public key, this user is the owner.
  return manager_->EnsurePrivateKey();
}

}  // namespace chromeos
<commit_msg>Fix chromeos browser_tests crash by skipping EnsurePrivateKey if device is not owned.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/ownership_service.h"

#include "base/file_path.h"
#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"

namespace chromeos {

//  static
OwnershipService* OwnershipService::GetSharedInstance() {
  return Singleton<OwnershipService>::get();
}

OwnershipService::OwnershipService()
    : manager_(new OwnerManager),
      utils_(OwnerKeyUtils::Create()) {
}

OwnershipService::~OwnershipService() {}

bool OwnershipService::IsAlreadyOwned() {
  return file_util::PathExists(utils_->GetOwnerKeyFilePath());
}

bool OwnershipService::StartLoadOwnerKeyAttempt() {
  if (!IsAlreadyOwned()) {
    LOG(WARNING) << "Device not yet owned";
    return false;
  }
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(), &OwnerManager::LoadOwnerKey));
  return true;
}

bool OwnershipService::StartTakeOwnershipAttempt() {
  if (IsAlreadyOwned()) {
    LOG(ERROR) << "Device is already owned";
    return false;
  }
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(),
                        &OwnerManager::GenerateKeysAndExportPublic));
  return true;
}

void OwnershipService::StartSigningAttempt(const std::string& data,
                                           OwnerManager::Delegate* d) {
  if (!IsAlreadyOwned()) {
    LOG(ERROR) << "Device not yet owned";
    d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
    return;
  }
  ChromeThread::ID thread_id;
  if (!ChromeThread::GetCurrentThreadIdentifier(&thread_id))
    thread_id = ChromeThread::UI;
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(),
                        &OwnerManager::Sign,
                        thread_id,
                        data, d));
  return;
}

void OwnershipService::StartVerifyAttempt(const std::string& data,
                                          const std::vector<uint8>& signature,
                                          OwnerManager::Delegate* d) {
  if (!IsAlreadyOwned()) {
    LOG(ERROR) << "Device not yet owned";
    d->OnKeyOpComplete(OwnerManager::KEY_UNAVAILABLE, std::vector<uint8>());
    return;
  }
  ChromeThread::ID thread_id;
  if (!ChromeThread::GetCurrentThreadIdentifier(&thread_id))
    thread_id = ChromeThread::UI;
  ChromeThread::PostTask(
      ChromeThread::FILE, FROM_HERE,
      NewRunnableMethod(manager_.get(),
                        &OwnerManager::Verify,
                        thread_id,
                        data,
                        signature,
                        d));
  return;
}

bool OwnershipService::CurrentUserIsOwner() {
  // If this user has the private key associated with the owner's
  // public key, this user is the owner.
  return IsAlreadyOwned() && manager_->EnsurePrivateKey();
}

}  // namespace chromeos
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/ui/setting_level_bubble.h"

#include <algorithm>

#include "ash/shell.h"
#include "chrome/browser/chromeos/login/base_login_display_host.h"
#include "chrome/browser/chromeos/login/login_display_host.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/webui_login_display.h"
#include "chrome/browser/chromeos/ui/setting_level_bubble_view.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/views/window.h"
#include "ui/gfx/screen.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/root_view.h"

using base::TimeDelta;
using base::TimeTicks;
using std::max;
using std::min;

namespace {

// How long should the bubble be shown onscreen whenever the setting changes?
const int kBubbleShowTimeoutMs = 1000;

// How long should the level initially take to move up or down when it changes?
// (The rate adapts to handle keyboard autorepeat.)
const int64 kInitialAnimationDurationMs = 200;

// Horizontal position of the center of the bubble on the screen: 0 is left
// edge, 0.5 is center, 1 is right edge.
const double kBubbleXRatio = 0.5;

// Vertical gap from the bottom of the screen in pixels.
const int kBubbleBottomGap = 30;

// Duration between animation frames.
// Chosen to match ui::SlideAnimation's kDefaultFramerateHz.
const int kAnimationIntervalMs = 1000 / 50;

double LimitPercent(double percent) {
  return min(max(percent, 0.0), 100.0);
}

}  // namespace

namespace chromeos {

// SettingLevelBubbleDelegateView ----------------------------------------------
class SettingLevelBubbleDelegateView : public views::BubbleDelegateView {
 public:
  // BubbleDelegate overrides:
  virtual gfx::Rect GetAnchorRect() OVERRIDE;

  // Create the bubble delegate view.
  SettingLevelBubbleDelegateView();
  virtual ~SettingLevelBubbleDelegateView();

  SettingLevelBubbleView* view() { return view_; }

 protected:
  // BubbleDelegate overrides:
  virtual void Init() OVERRIDE;

 private:
  SettingLevelBubbleView* view_;

  DISALLOW_COPY_AND_ASSIGN(SettingLevelBubbleDelegateView);
};

gfx::Rect SettingLevelBubbleDelegateView::GetAnchorRect() {
  gfx::Size view_size = GetPreferredSize();
  // Calculate the position in screen coordinates that the bubble should
  // "point" at (since we use BubbleBorder::FLOAT, this position actually
  // specifies the center of the bubble).
  gfx::Rect monitor_area = gfx::Screen::GetMonitorAreaNearestWindow(NULL);
  return (gfx::Rect(
      monitor_area.x() + kBubbleXRatio * monitor_area.width(),
      monitor_area.bottom() - view_size.height() / 2 - kBubbleBottomGap, 0, 0));
}

SettingLevelBubbleDelegateView::SettingLevelBubbleDelegateView()
    : BubbleDelegateView(NULL, views::BubbleBorder::FLOAT),
      view_(NULL) {
  set_close_on_esc(false);
  set_use_focusless(true);
}

SettingLevelBubbleDelegateView::~SettingLevelBubbleDelegateView() {
  view_ = NULL;
}

void SettingLevelBubbleDelegateView::Init() {
  SetLayoutManager(new views::FillLayout());
  view_ = new SettingLevelBubbleView();
  AddChildView(view_);
}

// SettingLevelBubble ----------------------------------------------------------
void SettingLevelBubble::ShowBubble(double percent, bool enabled) {
  if (ash::Shell::GetInstance()->tray())
    return;
  hide_timer_.Stop();

  // Set up target percent and icon.
  const double old_target_percent = target_percent_;
  UpdateTargetPercent(percent);
  SkBitmap* current_icon = increase_icon_;
  if (!enabled || target_percent_ == 0)
    current_icon = disabled_icon_;
  else if (old_target_percent >= 0 && target_percent_ < old_target_percent)
    current_icon = decrease_icon_;

  if (!view_) {
    view_ = CreateView();
    view_->Init(current_icon, percent, enabled);
  } else {
    // Reset fade sequence, if the bubble is already fading.
    SettingLevelBubbleDelegateView* delegate =
        static_cast<SettingLevelBubbleDelegateView*>
        (view_->GetWidget()->widget_delegate());
    delegate->ResetFade();
    view_->SetIcon(current_icon);
    view_->SetEnabled(enabled);
  }
  view_->GetWidget()->Show();
  // When the timer runs out, start the fade sequence.
  hide_timer_.Start(FROM_HERE,
                    base::TimeDelta::FromMilliseconds(kBubbleShowTimeoutMs),
                    this, &SettingLevelBubble::OnHideTimeout);
}

void SettingLevelBubble::HideBubble() {
  if (ash::Shell::GetInstance()->tray())
    return;
  hide_timer_.Stop();
  if (view_) {
    view_->GetWidget()->Close();
    view_ = NULL;
  }
}

void SettingLevelBubble::UpdateWithoutShowingBubble(double percent,
                                                    bool enabled) {
  UpdateTargetPercent(percent);
  if (view_)
    view_->SetEnabled(enabled);
}

SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
                                       SkBitmap* decrease_icon,
                                       SkBitmap* disabled_icon)
    :  current_percent_(-1.0),
       target_percent_(-1.0),
       increase_icon_(increase_icon),
       decrease_icon_(decrease_icon),
       disabled_icon_(disabled_icon),
       view_(NULL),
       is_animating_(false) {
}

SettingLevelBubble::~SettingLevelBubble() {
  view_ = NULL;
}

void SettingLevelBubble::OnWidgetClosing(views::Widget* widget) {
  if (view_ && view_->GetWidget() == widget) {
    view_->GetWidget()->RemoveObserver(this);
    view_ = NULL;
  }
  // Update states.
  current_percent_ = target_percent_;
  target_time_ = TimeTicks();
  last_animation_update_time_ = TimeTicks();
  last_target_update_time_ = TimeTicks();
  hide_timer_.Stop();
  StopAnimation();
}

SettingLevelBubbleView* SettingLevelBubble::CreateView() {
  SettingLevelBubbleDelegateView* delegate = new SettingLevelBubbleDelegateView;
  views::Widget* widget = browser::CreateViewsBubbleAboveLockScreen(delegate);
  widget->AddObserver(this);
  // Hold on to the content view.
  return delegate->view();
}

void SettingLevelBubble::OnHideTimeout() {
  // Start fading away.
  if (view_) {
    SettingLevelBubbleDelegateView* delegate =
        static_cast<SettingLevelBubbleDelegateView*>
        (view_->GetWidget()->widget_delegate());
    delegate->StartFade(false);
  }
}

void SettingLevelBubble::OnAnimationTimeout() {
  const TimeTicks now = TimeTicks::Now();
  const int64 remaining_ms = (target_time_ - now).InMilliseconds();

  if (remaining_ms <= 0) {
    current_percent_ = target_percent_;
    StopAnimation();
  } else {
    // Figure out what fraction of the total time until we want to reach the
    // target has elapsed since the last update.
    const double remaining_percent = target_percent_ - current_percent_;
    const int64 elapsed_ms =
        (now - last_animation_update_time_).InMilliseconds();
    current_percent_ +=
        remaining_percent *
        (static_cast<double>(elapsed_ms) / (elapsed_ms + remaining_ms));
  }
  last_animation_update_time_ = now;

  if (view_)
    view_->SetLevel(current_percent_);
}

void SettingLevelBubble::UpdateTargetPercent(double percent) {
  target_percent_ = LimitPercent(percent);
  const TimeTicks now = TimeTicks::Now();

  if (current_percent_ < 0.0) {
    // If we're setting the level for the first time, no need to animate.
    current_percent_ = target_percent_;
    if (view_)
      view_->SetLevel(current_percent_);
  } else {
    // Use the time since the last request as a hint for the duration of the
    // animation.  This makes us automatically adapt to the repeat rate if a key
    // is being held down to change a setting (which prevents us from lagging
    // behind when the key is finally released).
    int64 duration_ms = kInitialAnimationDurationMs;
    if (!last_target_update_time_.is_null())
      duration_ms = min(kInitialAnimationDurationMs,
                        (now - last_target_update_time_).InMilliseconds());
    target_time_ = now + TimeDelta::FromMilliseconds(duration_ms);

    if (!is_animating_) {
      animation_timer_.Start(FROM_HERE,
                             TimeDelta::FromMilliseconds(kAnimationIntervalMs),
                             this,
                             &SettingLevelBubble::OnAnimationTimeout);
      is_animating_ = true;
      last_animation_update_time_ = now;
    }
  }

  last_target_update_time_ = now;
}

void SettingLevelBubble::StopAnimation() {
  animation_timer_.Stop();
  is_animating_ = false;
}

}  // namespace chromeos
<commit_msg>Revert 127487 because it broke some browser-tests. --- chromeos: Do not show the old setting bubbles when volume/brightness changes if the uber-tray is active.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/ui/setting_level_bubble.h"

#include <algorithm>

#include "chrome/browser/chromeos/login/base_login_display_host.h"
#include "chrome/browser/chromeos/login/login_display_host.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/webui_login_display.h"
#include "chrome/browser/chromeos/ui/setting_level_bubble_view.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/views/window.h"
#include "ui/gfx/screen.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/root_view.h"

using base::TimeDelta;
using base::TimeTicks;
using std::max;
using std::min;

namespace {

// How long should the bubble be shown onscreen whenever the setting changes?
const int kBubbleShowTimeoutMs = 1000;

// How long should the level initially take to move up or down when it changes?
// (The rate adapts to handle keyboard autorepeat.)
const int64 kInitialAnimationDurationMs = 200;

// Horizontal position of the center of the bubble on the screen: 0 is left
// edge, 0.5 is center, 1 is right edge.
const double kBubbleXRatio = 0.5;

// Vertical gap from the bottom of the screen in pixels.
const int kBubbleBottomGap = 30;

// Duration between animation frames.
// Chosen to match ui::SlideAnimation's kDefaultFramerateHz.
const int kAnimationIntervalMs = 1000 / 50;

double LimitPercent(double percent) {
  return min(max(percent, 0.0), 100.0);
}

}  // namespace

namespace chromeos {

// SettingLevelBubbleDelegateView ----------------------------------------------
class SettingLevelBubbleDelegateView : public views::BubbleDelegateView {
 public:
  // BubbleDelegate overrides:
  virtual gfx::Rect GetAnchorRect() OVERRIDE;

  // Create the bubble delegate view.
  SettingLevelBubbleDelegateView();
  virtual ~SettingLevelBubbleDelegateView();

  SettingLevelBubbleView* view() { return view_; }

 protected:
  // BubbleDelegate overrides:
  virtual void Init() OVERRIDE;

 private:
  SettingLevelBubbleView* view_;

  DISALLOW_COPY_AND_ASSIGN(SettingLevelBubbleDelegateView);
};

gfx::Rect SettingLevelBubbleDelegateView::GetAnchorRect() {
  gfx::Size view_size = GetPreferredSize();
  // Calculate the position in screen coordinates that the bubble should
  // "point" at (since we use BubbleBorder::FLOAT, this position actually
  // specifies the center of the bubble).
  gfx::Rect monitor_area = gfx::Screen::GetMonitorAreaNearestWindow(NULL);
  return (gfx::Rect(
      monitor_area.x() + kBubbleXRatio * monitor_area.width(),
      monitor_area.bottom() - view_size.height() / 2 - kBubbleBottomGap, 0, 0));
}

SettingLevelBubbleDelegateView::SettingLevelBubbleDelegateView()
    : BubbleDelegateView(NULL, views::BubbleBorder::FLOAT),
      view_(NULL) {
  set_close_on_esc(false);
  set_use_focusless(true);
}

SettingLevelBubbleDelegateView::~SettingLevelBubbleDelegateView() {
  view_ = NULL;
}

void SettingLevelBubbleDelegateView::Init() {
  SetLayoutManager(new views::FillLayout());
  view_ = new SettingLevelBubbleView();
  AddChildView(view_);
}

// SettingLevelBubble ----------------------------------------------------------
void SettingLevelBubble::ShowBubble(double percent, bool enabled) {
  hide_timer_.Stop();

  // Set up target percent and icon.
  const double old_target_percent = target_percent_;
  UpdateTargetPercent(percent);
  SkBitmap* current_icon = increase_icon_;
  if (!enabled || target_percent_ == 0)
    current_icon = disabled_icon_;
  else if (old_target_percent >= 0 && target_percent_ < old_target_percent)
    current_icon = decrease_icon_;

  if (!view_) {
    view_ = CreateView();
    view_->Init(current_icon, percent, enabled);
  } else {
    // Reset fade sequence, if the bubble is already fading.
    SettingLevelBubbleDelegateView* delegate =
        static_cast<SettingLevelBubbleDelegateView*>
        (view_->GetWidget()->widget_delegate());
    delegate->ResetFade();
    view_->SetIcon(current_icon);
    view_->SetEnabled(enabled);
  }
  view_->GetWidget()->Show();
  // When the timer runs out, start the fade sequence.
  hide_timer_.Start(FROM_HERE,
                    base::TimeDelta::FromMilliseconds(kBubbleShowTimeoutMs),
                    this, &SettingLevelBubble::OnHideTimeout);
}

void SettingLevelBubble::HideBubble() {
  hide_timer_.Stop();
  if (view_) {
    view_->GetWidget()->Close();
    view_ = NULL;
  }
}

void SettingLevelBubble::UpdateWithoutShowingBubble(double percent,
                                                    bool enabled) {
  UpdateTargetPercent(percent);
  if (view_)
    view_->SetEnabled(enabled);
}

SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
                                       SkBitmap* decrease_icon,
                                       SkBitmap* disabled_icon)
    :  current_percent_(-1.0),
       target_percent_(-1.0),
       increase_icon_(increase_icon),
       decrease_icon_(decrease_icon),
       disabled_icon_(disabled_icon),
       view_(NULL),
       is_animating_(false) {
}

SettingLevelBubble::~SettingLevelBubble() {
  view_ = NULL;
}

void SettingLevelBubble::OnWidgetClosing(views::Widget* widget) {
  if (view_ && view_->GetWidget() == widget) {
    view_->GetWidget()->RemoveObserver(this);
    view_ = NULL;
  }
  // Update states.
  current_percent_ = target_percent_;
  target_time_ = TimeTicks();
  last_animation_update_time_ = TimeTicks();
  last_target_update_time_ = TimeTicks();
  hide_timer_.Stop();
  StopAnimation();
}

SettingLevelBubbleView* SettingLevelBubble::CreateView() {
  SettingLevelBubbleDelegateView* delegate = new SettingLevelBubbleDelegateView;
  views::Widget* widget = browser::CreateViewsBubbleAboveLockScreen(delegate);
  widget->AddObserver(this);
  // Hold on to the content view.
  return delegate->view();
}

void SettingLevelBubble::OnHideTimeout() {
  // Start fading away.
  if (view_) {
    SettingLevelBubbleDelegateView* delegate =
        static_cast<SettingLevelBubbleDelegateView*>
        (view_->GetWidget()->widget_delegate());
    delegate->StartFade(false);
  }
}

void SettingLevelBubble::OnAnimationTimeout() {
  const TimeTicks now = TimeTicks::Now();
  const int64 remaining_ms = (target_time_ - now).InMilliseconds();

  if (remaining_ms <= 0) {
    current_percent_ = target_percent_;
    StopAnimation();
  } else {
    // Figure out what fraction of the total time until we want to reach the
    // target has elapsed since the last update.
    const double remaining_percent = target_percent_ - current_percent_;
    const int64 elapsed_ms =
        (now - last_animation_update_time_).InMilliseconds();
    current_percent_ +=
        remaining_percent *
        (static_cast<double>(elapsed_ms) / (elapsed_ms + remaining_ms));
  }
  last_animation_update_time_ = now;

  if (view_)
    view_->SetLevel(current_percent_);
}

void SettingLevelBubble::UpdateTargetPercent(double percent) {
  target_percent_ = LimitPercent(percent);
  const TimeTicks now = TimeTicks::Now();

  if (current_percent_ < 0.0) {
    // If we're setting the level for the first time, no need to animate.
    current_percent_ = target_percent_;
    if (view_)
      view_->SetLevel(current_percent_);
  } else {
    // Use the time since the last request as a hint for the duration of the
    // animation.  This makes us automatically adapt to the repeat rate if a key
    // is being held down to change a setting (which prevents us from lagging
    // behind when the key is finally released).
    int64 duration_ms = kInitialAnimationDurationMs;
    if (!last_target_update_time_.is_null())
      duration_ms = min(kInitialAnimationDurationMs,
                        (now - last_target_update_time_).InMilliseconds());
    target_time_ = now + TimeDelta::FromMilliseconds(duration_ms);

    if (!is_animating_) {
      animation_timer_.Start(FROM_HERE,
                             TimeDelta::FromMilliseconds(kAnimationIntervalMs),
                             this,
                             &SettingLevelBubble::OnAnimationTimeout);
      is_animating_ = true;
      last_animation_update_time_ = now;
    }
  }

  last_target_update_time_ = now;
}

void SettingLevelBubble::StopAnimation() {
  animation_timer_.Stop();
  is_animating_ = false;
}

}  // namespace chromeos
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/image_loading_tracker.h"

#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/image_decoder.h"

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker::ImageLoader

// A RefCounted class for loading images on the File thread and reporting back
// on the UI thread.
class ImageLoadingTracker::ImageLoader
    : public base::RefCountedThreadSafe<ImageLoader> {
 public:
  explicit ImageLoader(ImageLoadingTracker* tracker)
      : tracker_(tracker) {
    CHECK(ChromeThread::GetCurrentThreadIdentifier(&callback_thread_id_));
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
  }

  // Lets this class know that the tracker is no longer interested in the
  // results.
  void StopTracking() {
    tracker_ = NULL;
  }

  // Instructs the loader to load a task on the File thread.
  void LoadImage(const ExtensionResource& resource,
                 const gfx::Size& max_size,
                 int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
    ChromeThread::PostTask(
        ChromeThread::FILE, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::LoadOnFileThread, resource,
                          max_size, id));
  }

  void LoadOnFileThread(ExtensionResource resource,
                        const gfx::Size& max_size,
                        int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    // Read the file from disk.
    std::string file_contents;
    FilePath path = resource.GetFilePath();
    if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) {
      ReportBack(NULL, resource, id);
      return;
    }

    // Decode the image using WebKit's image decoder.
    const unsigned char* data =
        reinterpret_cast<const unsigned char*>(file_contents.data());
    webkit_glue::ImageDecoder decoder;
    scoped_ptr<SkBitmap> decoded(new SkBitmap());
    *decoded = decoder.Decode(data, file_contents.length());
    if (decoded->empty()) {
      ReportBack(NULL, resource, id);
      return;  // Unable to decode.
    }

    if (decoded->width() > max_size.width() ||
        decoded->height() > max_size.height()) {
      // The bitmap is too big, re-sample.
      *decoded = skia::ImageOperations::Resize(
          *decoded, skia::ImageOperations::RESIZE_LANCZOS3,
          max_size.width(), max_size.height());
    }

    ReportBack(decoded.release(), resource, id);
  }

  void ReportBack(SkBitmap* image, const ExtensionResource& resource,
                  int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    ChromeThread::PostTask(
        callback_thread_id_, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::ReportOnUIThread,
                          image, resource, id));
  }

  void ReportOnUIThread(SkBitmap* image, ExtensionResource resource,
                        int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));

    if (tracker_)
      tracker_->OnImageLoaded(image, resource, id);

    delete image;
  }

 private:
  // The tracker we are loading the image for. If NULL, it means the tracker is
  // no longer interested in the reply.
  ImageLoadingTracker* tracker_;

  // The thread that we need to call back on to report that we are done.
  ChromeThread::ID callback_thread_id_;

  DISALLOW_COPY_AND_ASSIGN(ImageLoader);
};

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker

ImageLoadingTracker::ImageLoadingTracker(Observer* observer)
    : observer_(observer),
      next_id_(0) {
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 NotificationService::AllSources());
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
                 NotificationService::AllSources());
}

ImageLoadingTracker::~ImageLoadingTracker() {
  // The loader is created lazily and is NULL if the tracker is destroyed before
  // any valid image load tasks have been posted.
  if (loader_)
    loader_->StopTracking();
}

void ImageLoadingTracker::LoadImage(Extension* extension,
                                    const ExtensionResource& resource,
                                    const gfx::Size& max_size,
                                    CacheParam cache) {
  DCHECK(extension->path() == resource.extension_root());

  // If we don't have a path we don't need to do any further work, just respond
  // back.
  int id = next_id_++;
  if (resource.relative_path().empty()) {
    OnImageLoaded(NULL, resource, id);
    return;
  }

  // See if the extension has the image already.
  if (extension->HasCachedImage(resource)) {
    SkBitmap image = extension->GetCachedImage(resource);
    OnImageLoaded(&image, resource, id);
    return;
  }

  if (cache == CACHE) {
    load_map_[id] = extension;
  }

  // Instruct the ImageLoader to load this on the File thread. LoadImage does
  // not block.
  if (!loader_)
    loader_ = new ImageLoader(this);
  loader_->LoadImage(resource, max_size, id);
}

void ImageLoadingTracker::OnImageLoaded(
    SkBitmap* image,
    const ExtensionResource& resource,
    int id) {
  LoadMap::iterator i = load_map_.find(id);
  if (i != load_map_.end()) {
    i->second->SetCachedImage(resource, image ? *image : SkBitmap());
    load_map_.erase(i);
  }

  observer_->OnImageLoaded(image, resource, id);
}

void ImageLoadingTracker::Observe(NotificationType type,
                                  const NotificationSource& source,
                                  const NotificationDetails& details) {
  DCHECK(type == NotificationType::EXTENSION_UNLOADED ||
         type == NotificationType::EXTENSION_UNLOADED_DISABLED);

  Extension* extension = Details<Extension>(details).ptr();

  // Remove all entries in the load_map_ referencing the extension. This ensures
  // we don't attempt to cache the image when the load completes.
  for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end();) {
    if (i->second == extension) {
      load_map_.erase(i++);
    } else {
      ++i;
    }
  }
}
<commit_msg>Fixes bug in ImageLoadintTracker where it would incorrectly hit a DCHECK if the extension doesn't have an image for a particular resource.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/image_loading_tracker.h"

#include "base/file_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/image_decoder.h"

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker::ImageLoader

// A RefCounted class for loading images on the File thread and reporting back
// on the UI thread.
class ImageLoadingTracker::ImageLoader
    : public base::RefCountedThreadSafe<ImageLoader> {
 public:
  explicit ImageLoader(ImageLoadingTracker* tracker)
      : tracker_(tracker) {
    CHECK(ChromeThread::GetCurrentThreadIdentifier(&callback_thread_id_));
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
  }

  // Lets this class know that the tracker is no longer interested in the
  // results.
  void StopTracking() {
    tracker_ = NULL;
  }

  // Instructs the loader to load a task on the File thread.
  void LoadImage(const ExtensionResource& resource,
                 const gfx::Size& max_size,
                 int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
    ChromeThread::PostTask(
        ChromeThread::FILE, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::LoadOnFileThread, resource,
                          max_size, id));
  }

  void LoadOnFileThread(ExtensionResource resource,
                        const gfx::Size& max_size,
                        int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    // Read the file from disk.
    std::string file_contents;
    FilePath path = resource.GetFilePath();
    if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) {
      ReportBack(NULL, resource, id);
      return;
    }

    // Decode the image using WebKit's image decoder.
    const unsigned char* data =
        reinterpret_cast<const unsigned char*>(file_contents.data());
    webkit_glue::ImageDecoder decoder;
    scoped_ptr<SkBitmap> decoded(new SkBitmap());
    *decoded = decoder.Decode(data, file_contents.length());
    if (decoded->empty()) {
      ReportBack(NULL, resource, id);
      return;  // Unable to decode.
    }

    if (decoded->width() > max_size.width() ||
        decoded->height() > max_size.height()) {
      // The bitmap is too big, re-sample.
      *decoded = skia::ImageOperations::Resize(
          *decoded, skia::ImageOperations::RESIZE_LANCZOS3,
          max_size.width(), max_size.height());
    }

    ReportBack(decoded.release(), resource, id);
  }

  void ReportBack(SkBitmap* image, const ExtensionResource& resource,
                  int id) {
    DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));

    ChromeThread::PostTask(
        callback_thread_id_, FROM_HERE,
        NewRunnableMethod(this, &ImageLoader::ReportOnUIThread,
                          image, resource, id));
  }

  void ReportOnUIThread(SkBitmap* image, ExtensionResource resource,
                        int id) {
    DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));

    if (tracker_)
      tracker_->OnImageLoaded(image, resource, id);

    delete image;
  }

 private:
  // The tracker we are loading the image for. If NULL, it means the tracker is
  // no longer interested in the reply.
  ImageLoadingTracker* tracker_;

  // The thread that we need to call back on to report that we are done.
  ChromeThread::ID callback_thread_id_;

  DISALLOW_COPY_AND_ASSIGN(ImageLoader);
};

////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker

ImageLoadingTracker::ImageLoadingTracker(Observer* observer)
    : observer_(observer),
      next_id_(0) {
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
                 NotificationService::AllSources());
  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED,
                 NotificationService::AllSources());
}

ImageLoadingTracker::~ImageLoadingTracker() {
  // The loader is created lazily and is NULL if the tracker is destroyed before
  // any valid image load tasks have been posted.
  if (loader_)
    loader_->StopTracking();
}

void ImageLoadingTracker::LoadImage(Extension* extension,
                                    const ExtensionResource& resource,
                                    const gfx::Size& max_size,
                                    CacheParam cache) {
  // If we don't have a path we don't need to do any further work, just respond
  // back.
  int id = next_id_++;
  if (resource.relative_path().empty()) {
    OnImageLoaded(NULL, resource, id);
    return;
  }

  DCHECK(extension->path() == resource.extension_root());

  // See if the extension has the image already.
  if (extension->HasCachedImage(resource)) {
    SkBitmap image = extension->GetCachedImage(resource);
    OnImageLoaded(&image, resource, id);
    return;
  }

  if (cache == CACHE) {
    load_map_[id] = extension;
  }

  // Instruct the ImageLoader to load this on the File thread. LoadImage does
  // not block.
  if (!loader_)
    loader_ = new ImageLoader(this);
  loader_->LoadImage(resource, max_size, id);
}

void ImageLoadingTracker::OnImageLoaded(
    SkBitmap* image,
    const ExtensionResource& resource,
    int id) {
  LoadMap::iterator i = load_map_.find(id);
  if (i != load_map_.end()) {
    i->second->SetCachedImage(resource, image ? *image : SkBitmap());
    load_map_.erase(i);
  }

  observer_->OnImageLoaded(image, resource, id);
}

void ImageLoadingTracker::Observe(NotificationType type,
                                  const NotificationSource& source,
                                  const NotificationDetails& details) {
  DCHECK(type == NotificationType::EXTENSION_UNLOADED ||
         type == NotificationType::EXTENSION_UNLOADED_DISABLED);

  Extension* extension = Details<Extension>(details).ptr();

  // Remove all entries in the load_map_ referencing the extension. This ensures
  // we don't attempt to cache the image when the load completes.
  for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end();) {
    if (i->second == extension) {
      load_map_.erase(i++);
    } else {
      ++i;
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <gtk/gtk.h>

#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/gtk/bookmark_editor_gtk.h"
#include "chrome/browser/gtk/bookmark_tree_model.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::Time;
using base::TimeDelta;
using bookmark_utils::GetTitleFromTreeIter;

// Base class for bookmark editor tests. This class is a copy from
// bookmark_editor_view_unittest.cc, and all the tests in this file are
// GTK-ifications of the corresponding views tests. Testing here is really
// important because on Linux, we make round trip copies from chrome's
// BookmarkModel class to GTK's native GtkTreeStore.
class BookmarkEditorGtkTest : public testing::Test {
 public:
  BookmarkEditorGtkTest() : model_(NULL) {
  }

  virtual void SetUp() {
    profile_.reset(new TestingProfile());
    profile_->set_has_history_service(true);
    profile_->CreateBookmarkModel(true);

    model_ = profile_->GetBookmarkModel();

    AddTestData();
  }

  virtual void TearDown() {
  }

 protected:
  MessageLoopForUI message_loop_;
  BookmarkModel* model_;
  scoped_ptr<TestingProfile> profile_;

  std::string base_path() const { return "file:///c:/tmp/"; }

  BookmarkNode* GetNode(const std::string& name) {
    return model_->GetMostRecentlyAddedNodeForURL(GURL(base_path() + name));
  }

 private:
  // Creates the following structure:
  // bookmark bar node
  //   a
  //   F1
  //    f1a
  //    F11
  //     f11a
  //   F2
  // other node
  //   oa
  //   OF1
  //     of1a
  void AddTestData() {
    std::string test_base = base_path();

    model_->AddURL(model_->GetBookmarkBarNode(), 0, L"a",
                   GURL(test_base + "a"));
    BookmarkNode* f1 = model_->AddGroup(model_->GetBookmarkBarNode(), 1, L"F1");
    model_->AddURL(f1, 0, L"f1a", GURL(test_base + "f1a"));
    BookmarkNode* f11 = model_->AddGroup(f1, 1, L"F11");
    model_->AddURL(f11, 0, L"f11a", GURL(test_base + "f11a"));
    model_->AddGroup(model_->GetBookmarkBarNode(), 2, L"F2");

    // Children of the other node.
    model_->AddURL(model_->other_node(), 0, L"oa",
                   GURL(test_base + "oa"));
    BookmarkNode* of1 = model_->AddGroup(model_->other_node(), 1, L"OF1");
    model_->AddURL(of1, 0, L"of1a", GURL(test_base + "of1a"));
  }
};

// Makes sure the tree model matches that of the bookmark bar model.
// Disabled: See crbug.com/15436
TEST_F(BookmarkEditorGtkTest, DISABLED_ModelsMatch) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, NULL,
                           BookmarkEditor::SHOW_TREE, NULL);

  // The root should have two children, one for the bookmark bar node,
  // the other for the 'other bookmarks' folder.
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  GtkTreeIter toplevel;
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &toplevel));
  GtkTreeIter bookmark_bar_node = toplevel;
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &toplevel));
  GtkTreeIter other_node = toplevel;
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &toplevel));

  // The bookmark bar should have 2 nodes: folder F1 and F2.
  GtkTreeIter f1_iter;
  GtkTreeIter child;
  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &bookmark_bar_node));
  f1_iter = child;
  ASSERT_EQ(L"F1", GetTitleFromTreeIter(store, &child));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &child));
  ASSERT_EQ(L"F2", GetTitleFromTreeIter(store, &child));
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));

  // F1 should have one child, F11
  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f1_iter));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &f1_iter));
  ASSERT_EQ(L"F11", GetTitleFromTreeIter(store, &child));
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));

  // Other node should have one child (OF1).
  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &other_node));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &other_node));
  ASSERT_EQ(L"OF1", GetTitleFromTreeIter(store, &child));
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
}

// Changes the title and makes sure parent/visual order doesn't change.
TEST_F(BookmarkEditorGtkTest, EditTitleKeepsPosition) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
  editor.ApplyEdits(&bookmark_bar_node);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  ASSERT_EQ(L"new_a", bb_node->GetChild(0)->GetTitle());
  // The URL shouldn't have changed.
  ASSERT_TRUE(GURL(base_path() + "a") == bb_node->GetChild(0)->GetURL());
}

// Changes the url and makes sure parent/visual order doesn't change.
TEST_F(BookmarkEditorGtkTest, EditURLKeepsPosition) {
  Time node_time = Time::Now() + TimeDelta::FromDays(2);
  GetNode("a")->date_added_ = node_time;
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);
  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "new_a").spec().c_str());

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
  editor.ApplyEdits(&bookmark_bar_node);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  ASSERT_EQ(L"a", bb_node->GetChild(0)->GetTitle());
  // The URL should have changed.
  ASSERT_TRUE(GURL(base_path() + "new_a") == bb_node->GetChild(0)->GetURL());
  ASSERT_TRUE(node_time == bb_node->GetChild(0)->date_added());
}

// Moves 'a' to be a child of the other node.
TEST_F(BookmarkEditorGtkTest, ChangeParent) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);

  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  GtkTreeIter gtk_other_node;
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
  editor.ApplyEdits(&gtk_other_node);

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(L"a", other_node->GetChild(2)->GetTitle());
  ASSERT_TRUE(GURL(base_path() + "a") == other_node->GetChild(2)->GetURL());
}

// Moves 'a' to be a child of the other node.
// Moves 'a' to be a child of the other node and changes its url to new_a.
TEST_F(BookmarkEditorGtkTest, ChangeParentAndURL) {
  Time node_time = Time::Now() + TimeDelta::FromDays(2);
  GetNode("a")->date_added_ = node_time;
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);

  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "new_a").spec().c_str());

  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  GtkTreeIter gtk_other_node;
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
  editor.ApplyEdits(&gtk_other_node);

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(L"a", other_node->GetChild(2)->GetTitle());
  ASSERT_TRUE(GURL(base_path() + "new_a") == other_node->GetChild(2)->GetURL());
  ASSERT_TRUE(node_time == other_node->GetChild(2)->date_added());
}

// Creates a new folder and moves a node to it.
TEST_F(BookmarkEditorGtkTest, MoveToNewParent) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));

  // The bookmark bar should have 2 nodes: folder F1 and F2.
  GtkTreeIter f2_iter;
  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &f2_iter,
                                           &bookmark_bar_node));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &f2_iter));

  // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21".
  GtkTreeIter f21_iter;
  editor.AddNewGroup(&f2_iter, &f21_iter);
  gtk_tree_store_set(editor.tree_store_, &f21_iter,
                     bookmark_utils::FOLDER_NAME, "F21", -1);
  GtkTreeIter f211_iter;
  editor.AddNewGroup(&f21_iter, &f211_iter);
  gtk_tree_store_set(editor.tree_store_, &f211_iter,
                     bookmark_utils::FOLDER_NAME, "F211", -1);

  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f2_iter));

  editor.ApplyEdits(&f2_iter);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  BookmarkNode* mf2 = bb_node->GetChild(1);

  // F2 in the model should have two children now: F21 and the node edited.
  ASSERT_EQ(2, mf2->GetChildCount());
  // F21 should be first.
  ASSERT_EQ(L"F21", mf2->GetChild(0)->GetTitle());
  // Then a.
  ASSERT_EQ(L"a", mf2->GetChild(1)->GetTitle());

  // F21 should have one child, F211.
  BookmarkNode* mf21 = mf2->GetChild(0);
  ASSERT_EQ(1, mf21->GetChildCount());
  ASSERT_EQ(L"F211", mf21->GetChild(0)->GetTitle());
}

// Brings up the editor, creating a new URL on the bookmark bar.
TEST_F(BookmarkEditorGtkTest, NewURL) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, NULL,
                           BookmarkEditor::SHOW_TREE, NULL);

  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "a").spec().c_str());
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
  editor.ApplyEdits(&bookmark_bar_node);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  ASSERT_EQ(4, bb_node->GetChildCount());

  BookmarkNode* new_node = bb_node->GetChild(3);
  EXPECT_EQ(L"new_a", new_node->GetTitle());
  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
}

// Brings up the editor with no tree and modifies the url.
TEST_F(BookmarkEditorGtkTest, ChangeURLNoTree) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
                           model_->other_node()->GetChild(0),
                           BookmarkEditor::NO_TREE, NULL);

  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "a").spec().c_str());
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  editor.ApplyEdits(NULL);

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(2, other_node->GetChildCount());

  BookmarkNode* new_node = other_node->GetChild(0);

  EXPECT_EQ(L"new_a", new_node->GetTitle());
  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
}

// Brings up the editor with no tree and modifies only the title.
TEST_F(BookmarkEditorGtkTest, ChangeTitleNoTree) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
                           model_->other_node()->GetChild(0),
                           BookmarkEditor::NO_TREE, NULL);
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  editor.ApplyEdits();

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(2, other_node->GetChildCount());

  BookmarkNode* new_node = other_node->GetChild(0);
  EXPECT_EQ(L"new_a", new_node->GetTitle());
}
<commit_msg>Fix breakage<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <gtk/gtk.h>

#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/gtk/bookmark_editor_gtk.h"
#include "chrome/browser/gtk/bookmark_tree_model.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/test/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::Time;
using base::TimeDelta;
using bookmark_utils::GetTitleFromTreeIter;

// Base class for bookmark editor tests. This class is a copy from
// bookmark_editor_view_unittest.cc, and all the tests in this file are
// GTK-ifications of the corresponding views tests. Testing here is really
// important because on Linux, we make round trip copies from chrome's
// BookmarkModel class to GTK's native GtkTreeStore.
class BookmarkEditorGtkTest : public testing::Test {
 public:
  BookmarkEditorGtkTest() : model_(NULL) {
  }

  virtual void SetUp() {
    profile_.reset(new TestingProfile());
    profile_->set_has_history_service(true);
    profile_->CreateBookmarkModel(true);

    model_ = profile_->GetBookmarkModel();

    AddTestData();
  }

  virtual void TearDown() {
  }

 protected:
  MessageLoopForUI message_loop_;
  BookmarkModel* model_;
  scoped_ptr<TestingProfile> profile_;

  std::string base_path() const { return "file:///c:/tmp/"; }

  BookmarkNode* GetNode(const std::string& name) {
    return model_->GetMostRecentlyAddedNodeForURL(GURL(base_path() + name));
  }

 private:
  // Creates the following structure:
  // bookmark bar node
  //   a
  //   F1
  //    f1a
  //    F11
  //     f11a
  //   F2
  // other node
  //   oa
  //   OF1
  //     of1a
  void AddTestData() {
    std::string test_base = base_path();

    model_->AddURL(model_->GetBookmarkBarNode(), 0, L"a",
                   GURL(test_base + "a"));
    BookmarkNode* f1 = model_->AddGroup(model_->GetBookmarkBarNode(), 1, L"F1");
    model_->AddURL(f1, 0, L"f1a", GURL(test_base + "f1a"));
    BookmarkNode* f11 = model_->AddGroup(f1, 1, L"F11");
    model_->AddURL(f11, 0, L"f11a", GURL(test_base + "f11a"));
    model_->AddGroup(model_->GetBookmarkBarNode(), 2, L"F2");

    // Children of the other node.
    model_->AddURL(model_->other_node(), 0, L"oa",
                   GURL(test_base + "oa"));
    BookmarkNode* of1 = model_->AddGroup(model_->other_node(), 1, L"OF1");
    model_->AddURL(of1, 0, L"of1a", GURL(test_base + "of1a"));
  }
};

// Makes sure the tree model matches that of the bookmark bar model.
// Disabled: See crbug.com/15436
#if 0
TEST_F(BookmarkEditorGtkTest, ModelsMatch) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, NULL,
                           BookmarkEditor::SHOW_TREE, NULL);

  // The root should have two children, one for the bookmark bar node,
  // the other for the 'other bookmarks' folder.
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  GtkTreeIter toplevel;
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &toplevel));
  GtkTreeIter bookmark_bar_node = toplevel;
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &toplevel));
  GtkTreeIter other_node = toplevel;
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &toplevel));

  // The bookmark bar should have 2 nodes: folder F1 and F2.
  GtkTreeIter f1_iter;
  GtkTreeIter child;
  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &bookmark_bar_node));
  f1_iter = child;
  ASSERT_EQ(L"F1", GetTitleFromTreeIter(store, &child));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &child));
  ASSERT_EQ(L"F2", GetTitleFromTreeIter(store, &child));
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));

  // F1 should have one child, F11
  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f1_iter));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &f1_iter));
  ASSERT_EQ(L"F11", GetTitleFromTreeIter(store, &child));
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));

  // Other node should have one child (OF1).
  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &other_node));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &child, &other_node));
  ASSERT_EQ(L"OF1", GetTitleFromTreeIter(store, &child));
  ASSERT_FALSE(gtk_tree_model_iter_next(store, &child));
}
#endif

// Changes the title and makes sure parent/visual order doesn't change.
TEST_F(BookmarkEditorGtkTest, EditTitleKeepsPosition) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
  editor.ApplyEdits(&bookmark_bar_node);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  ASSERT_EQ(L"new_a", bb_node->GetChild(0)->GetTitle());
  // The URL shouldn't have changed.
  ASSERT_TRUE(GURL(base_path() + "a") == bb_node->GetChild(0)->GetURL());
}

// Changes the url and makes sure parent/visual order doesn't change.
TEST_F(BookmarkEditorGtkTest, EditURLKeepsPosition) {
  Time node_time = Time::Now() + TimeDelta::FromDays(2);
  GetNode("a")->date_added_ = node_time;
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);
  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "new_a").spec().c_str());

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
  editor.ApplyEdits(&bookmark_bar_node);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  ASSERT_EQ(L"a", bb_node->GetChild(0)->GetTitle());
  // The URL should have changed.
  ASSERT_TRUE(GURL(base_path() + "new_a") == bb_node->GetChild(0)->GetURL());
  ASSERT_TRUE(node_time == bb_node->GetChild(0)->date_added());
}

// Moves 'a' to be a child of the other node.
TEST_F(BookmarkEditorGtkTest, ChangeParent) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);

  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  GtkTreeIter gtk_other_node;
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
  editor.ApplyEdits(&gtk_other_node);

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(L"a", other_node->GetChild(2)->GetTitle());
  ASSERT_TRUE(GURL(base_path() + "a") == other_node->GetChild(2)->GetURL());
}

// Moves 'a' to be a child of the other node.
// Moves 'a' to be a child of the other node and changes its url to new_a.
TEST_F(BookmarkEditorGtkTest, ChangeParentAndURL) {
  Time node_time = Time::Now() + TimeDelta::FromDays(2);
  GetNode("a")->date_added_ = node_time;
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);

  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "new_a").spec().c_str());

  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  GtkTreeIter gtk_other_node;
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &gtk_other_node));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &gtk_other_node));
  editor.ApplyEdits(&gtk_other_node);

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(L"a", other_node->GetChild(2)->GetTitle());
  ASSERT_TRUE(GURL(base_path() + "new_a") == other_node->GetChild(2)->GetURL());
  ASSERT_TRUE(node_time == other_node->GetChild(2)->date_added());
}

// Creates a new folder and moves a node to it.
TEST_F(BookmarkEditorGtkTest, MoveToNewParent) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, GetNode("a"),
                           BookmarkEditor::SHOW_TREE, NULL);

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));

  // The bookmark bar should have 2 nodes: folder F1 and F2.
  GtkTreeIter f2_iter;
  ASSERT_EQ(2, gtk_tree_model_iter_n_children(store, &bookmark_bar_node));
  ASSERT_TRUE(gtk_tree_model_iter_children(store, &f2_iter,
                                           &bookmark_bar_node));
  ASSERT_TRUE(gtk_tree_model_iter_next(store, &f2_iter));

  // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21".
  GtkTreeIter f21_iter;
  editor.AddNewGroup(&f2_iter, &f21_iter);
  gtk_tree_store_set(editor.tree_store_, &f21_iter,
                     bookmark_utils::FOLDER_NAME, "F21", -1);
  GtkTreeIter f211_iter;
  editor.AddNewGroup(&f21_iter, &f211_iter);
  gtk_tree_store_set(editor.tree_store_, &f211_iter,
                     bookmark_utils::FOLDER_NAME, "F211", -1);

  ASSERT_EQ(1, gtk_tree_model_iter_n_children(store, &f2_iter));

  editor.ApplyEdits(&f2_iter);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  BookmarkNode* mf2 = bb_node->GetChild(1);

  // F2 in the model should have two children now: F21 and the node edited.
  ASSERT_EQ(2, mf2->GetChildCount());
  // F21 should be first.
  ASSERT_EQ(L"F21", mf2->GetChild(0)->GetTitle());
  // Then a.
  ASSERT_EQ(L"a", mf2->GetChild(1)->GetTitle());

  // F21 should have one child, F211.
  BookmarkNode* mf21 = mf2->GetChild(0);
  ASSERT_EQ(1, mf21->GetChildCount());
  ASSERT_EQ(L"F211", mf21->GetChild(0)->GetTitle());
}

// Brings up the editor, creating a new URL on the bookmark bar.
TEST_F(BookmarkEditorGtkTest, NewURL) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL, NULL,
                           BookmarkEditor::SHOW_TREE, NULL);

  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "a").spec().c_str());
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  GtkTreeIter bookmark_bar_node;
  GtkTreeModel* store = GTK_TREE_MODEL(editor.tree_store_);
  ASSERT_TRUE(gtk_tree_model_get_iter_first(store, &bookmark_bar_node));
  editor.ApplyEdits(&bookmark_bar_node);

  BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode();
  ASSERT_EQ(4, bb_node->GetChildCount());

  BookmarkNode* new_node = bb_node->GetChild(3);
  EXPECT_EQ(L"new_a", new_node->GetTitle());
  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
}

// Brings up the editor with no tree and modifies the url.
TEST_F(BookmarkEditorGtkTest, ChangeURLNoTree) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
                           model_->other_node()->GetChild(0),
                           BookmarkEditor::NO_TREE, NULL);

  gtk_entry_set_text(GTK_ENTRY(editor.url_entry_),
                     GURL(base_path() + "a").spec().c_str());
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  editor.ApplyEdits(NULL);

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(2, other_node->GetChildCount());

  BookmarkNode* new_node = other_node->GetChild(0);

  EXPECT_EQ(L"new_a", new_node->GetTitle());
  EXPECT_TRUE(GURL(base_path() + "a") == new_node->GetURL());
}

// Brings up the editor with no tree and modifies only the title.
TEST_F(BookmarkEditorGtkTest, ChangeTitleNoTree) {
  BookmarkEditorGtk editor(NULL, profile_.get(), NULL,
                           model_->other_node()->GetChild(0),
                           BookmarkEditor::NO_TREE, NULL);
  gtk_entry_set_text(GTK_ENTRY(editor.name_entry_), "new_a");

  editor.ApplyEdits();

  BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node();
  ASSERT_EQ(2, other_node->GetChildCount());

  BookmarkNode* new_node = other_node->GetChild(0);
  EXPECT_EQ(L"new_a", new_node->GetTitle());
}
<|endoftext|>


<commit_before><commit_msg>Enable back the test disabled in r19348,r19345 since dank disabled them from valgrind itself.<commit_after><|endoftext|>


<commit_before>#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C&lang=jp"
#include <iostream>
#include <limits>
#include <vector>
using namespace std;
using ll = long long;

template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}

// ----- WarshallFloyd -----

template <typename T>
void WarshallFloyd(vector<vector<T>> &V, T infinity = numeric_limits<T>::max())
{
  // It is valid to apply this method for
  //  - a directed/undirected graph,
  //  - a graph whose edge may be negative.
  //    - Negative cycle can be detected by V[i][i] < 0 if we initialize V[i][i] = 0.
  auto N{static_cast<int>(V.size())};
  for (auto k{0}; k < N; ++k)
  {
    for (auto i{0}; i < N; ++i)
    {
      for (auto j{0}; j < N; ++j)
      {
        if (V[i][k] == infinity || V[k][j] == infinity)
        {
          continue;
        }
        ch_min(V[i][j], V[i][k] + V[k][j]);
      }
    }
  }
}

// ----- main -----

template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }

int main()
{
  int N, M;
  cin >> N >> M;
  vector<vector<ll>> D(N, vector<ll>(N, Infty<ll>()));
  for (auto i{0}; i < M; ++i)
  {
    int A, B;
    ll C;
    cin >> A >> B >> C;
    D[A][B] = C;
  }
  for (auto i{0}; i < N; ++i)
  {
    D[i][i] = 0;
  }
  WarshallFloyd(D);
  for (auto i{0}; i < N; ++i)
  {
    if (D[i][i] < 0)
    {
      cout << "NEGATIVE CYCLE" << endl;
      return 0;
    }
  }
  for (auto i{0}; i < N; ++i)
  {
    for (auto j{0}; j < N; ++j)
    {
      cout << (D[i][j] == Infty<ll>() ? "INF" : to_string(D[i][j]));
      if (j < N - 1)
      {
        cout << " ";
      }
      else
      {
        cout << endl;
      }
    }
  }
}
<commit_msg>WarshallFloyd<commit_after>#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/1/GRL_1_C"
#include <iostream>
#include <limits>
#include <vector>
using namespace std;
using ll = long long;

template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}

// ----- WarshallFloyd -----

template <typename T>
void WarshallFloyd(vector<vector<T>> &V, T infinity = numeric_limits<T>::max())
{
  // It is valid to apply this method for
  //  - a directed/undirected graph,
  //  - a graph whose edge may be negative.
  //    - Negative cycle can be detected by V[i][i] < 0 if we initialize V[i][i] = 0.
  auto N{static_cast<int>(V.size())};
  for (auto k{0}; k < N; ++k)
  {
    for (auto i{0}; i < N; ++i)
    {
      for (auto j{0}; j < N; ++j)
      {
        if (V[i][k] == infinity || V[k][j] == infinity)
        {
          continue;
        }
        ch_min(V[i][j], V[i][k] + V[k][j]);
      }
    }
  }
}

// ----- main -----

template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }

int main()
{
  int N, M;
  cin >> N >> M;
  vector<vector<ll>> D(N, vector<ll>(N, Infty<ll>()));
  for (auto i{0}; i < M; ++i)
  {
    int A, B;
    ll C;
    cin >> A >> B >> C;
    D[A][B] = C;
  }
  for (auto i{0}; i < N; ++i)
  {
    D[i][i] = 0;
  }
  WarshallFloyd(D);
  for (auto i{0}; i < N; ++i)
  {
    if (D[i][i] < 0)
    {
      cout << "NEGATIVE CYCLE" << endl;
      return 0;
    }
  }
  for (auto i{0}; i < N; ++i)
  {
    for (auto j{0}; j < N; ++j)
    {
      cout << (D[i][j] == Infty<ll>() ? "INF" : to_string(D[i][j]));
      if (j < N - 1)
      {
        cout << " ";
      }
      else
      {
        cout << endl;
      }
    }
  }
}
<|endoftext|>